【问题标题】:Python itertools product, but conditional?Python itertools 产品,但有条件?
【发布时间】:2014-01-30 18:33:13
【问题描述】:

我有一个 fun 函数,它接受多个参数 p0,p1,.. 对于每个参数,我给出一个可能值的列表:

p0_list = ['a','b','c']
p1_list = [5,100]

我现在可以为 p0,p1 的每个组合调用我的函数

for i in itertools.product(*[p0,p1]):
    print fun(i)

现在问题来了:如果我已经知道参数 p1 只对 fun 的结果有影响,如果 p0 是 'a' 或 'c' 怎么办?在这种情况下,我需要我的参数组合列表如下所示:

[('a', 5), ('a',100), ('b', 5), ('c',5), ('c', 100)]

所以 ('b', 100) 只是被省略了,因为它是对乐趣的不必要的评估。

我的最终解决方案

param_lists = [['p0', ['a','b','c']],['p1', [5,100]]]
l = itertools.product(*[x[1] for x in param_lists])
l = [x for x in l if not x[0] == 'b' or x[1]==5]

我将这种方法用于 5 个参数和各种条件,效果很好。它也很容易阅读。此代码的灵感来自 Corley Brigmans 和 nmcleans 的答案。

【问题讨论】:

  • 我个人会记住你的函数调用并用每个组合调用它。
  • 这需要一种方法来判断哪些组合会产生相同的结果,然后我就有机会删除这些组合。对吗?

标签: python python-2.7 product itertools


【解决方案1】:

这里有一个通用的过滤器函数可以解决这个问题:

def without_duplicate_item(groups, index, item):
    seen = False
    for group in groups:
        if group[index] == item:
            if seen:
                continue
            seen = True
        yield group

用法:

param_groups = itertools.product(*[p0_list, p1_list])

param_groups = without_duplicate_item(param_groups, 0, "b")

您当然可以继续为不同的参数添加过滤器。与存储以前的调用相比,这应该是相当节省内存的,因为它基本上每个过滤器只存储一个布尔值seen

【讨论】:

    【解决方案2】:

    您可以生成它,然后禁止“重复”。但最好单独生成:

    p0_list = ['a', 'b', 'c']
    p0_noarg1 = ['b']
    sp0_noarg1 = set(p0_noarg1)
    p0_arg1 = [x for x in p0_list if x not in sp0_noarg1]
    p1_list = [5, 100]
    
    total_list = [x for x in itertools.product(p0_arg1, p1_list)] + [x for x in itertools.product(p0_noarg1, p1_list[:1])]
    

    【讨论】:

    • 非常感谢,这行得通!但是,当处理 2+ 参数时,解决方案当然是讨厌的。但是我不认为我可以期待一个更优雅的解决方案,因为问题是如此令人讨厌。
    • 你能告诉我为什么你在这里使用 set() 吗?我试过了,它也可以在没有 set() 的情况下工作。
    • set(又名哈希表)中查找一个项目是一个 O(1) 操作——它或多或少是固定时间——你计算它应该在哪里的索引,看看那里,它是要么存在,要么不存在(忽略散列冲突,这应该很少见)。在list 中查找一个项目是一个 O(n) 操作 - 您必须每次都查看每个项目以确定该项目不存在。首先生成集合确实需要少量时间,但几乎总是值得的。
    • 顺便说一句,它没有理由不能扩展到多个参数 - 如果你需要我把它写出来,我可以试试,但作为一个提示:product(a,b,c) == product(*[a,b,c])。 ..
    • @CorleyBrigman 不过,这会在每次迭代中创建一个新集合。要获得速度优势,您需要将 set 调用移出列表理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 2020-05-05
    • 2015-10-28
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多