如何生成不重复的 itertools 产品?

How to generate itertools product without duplicates?

我想我列出了一个错误的例子,对此我深表歉意,已经用另一个例子重新编辑了这个,请看这个版本。

我知道有一个非常相似的问题:Itertools product without repeating duplicates

但我有一些东西 different.For 示例:

a = ['add', 'sub']
b = [2,3, 'a', 'b']
c = [1,3, 'a', 'c']
list(it.product(a, b, c))  # result is:[('add', 2, 1),('add', 2, 3),('add', 2, 'a'), ('add', 2, 'c'),
#('add', 3, 1),('add', 3, 3),('add', 3, 'a'),('add', 3, 'c'),('add', 'a', 1),('add', 'a', 3),
#('add', 'a', 'a'),('add', 'a', 'c'), ('add', 'b', 1),('add', 'b', 3),('add', 'b', 'a'),
#('add', 'b', 'c'),('sub', 2, 1),('sub', 2, 3),('sub', 2, 'a'),('sub', 2, 'c'),('sub', 3, 1),
#('sub', 3, 3),('sub', 3, 'a'),('sub', 3, 'c'),('sub', 'a', 1),('sub', 'a', 3),('sub', 'a', 'a'),
#('sub', 'a', 'c'),('sub', 'b', 1),('sub', 'b', 3),('sub', 'b', 'a'),('sub', 'b', 'c')]

为结果:

我不想添加 (a,a),因为第一个值 == 第二个值

我只想保留 add(3,a) add(a,3) 中的 1 个,因为它是对称的。

我的示例只包含两个列表,但我可能会使用 5 个或更多列表来生成产品。

我不能使用组合,因为:

product(['add', 'sub', 1,2,3, 'a','b', 'c'], repeat=3) 是与产品不同(['add', 'sub'], [2,3, 'a', 'b'], [1,3, 'a', 'c'])

产品中的东西(['add', 'sub', 1,2,3, 'a','b', 'c'], 重复=3 ) 不适合我。

我想要一个快速的方法,因为我的程序对时间很敏感。

有人可以帮忙吗?

既然你已经把它转换成一个列表,你可以做一个列表理解来过滤掉0索引值等于1索引值的元组。


filtered_list = [(a, b) for a, b in unfiltered_list if a != b]

def filter_symmetry(_list):
    checked_elements = []
    if not len(_list):
        return

    for a, b in _list:
        if (b, a) not in checked_elements:
            checked_elements.append((a, b))

    return checked_elements

filtered_list = filter_symmetry(filtered_list)

我想这就是你想要做的。

应该这样做:

import itertools


def generate_without_duplicates(*inputs):
    seen = set()
    for prod in itertools.product(*inputs):
        prod_set = frozenset(prod)
        if len(prod_set) == 1:  # all items are the same
            continue
        if prod_set not in seen:
            seen.add(prod_set)
            yield prod


a = [1, 2, 3]
b = [2, 3, 4]

for val in generate_without_duplicates(a, b):
    print(val)

输出为

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)

您可以采用 itertools.product 的实现,对其进行调整以使其符合您的要求:

def product_without_dupl(*args, repeat=1):
    pools = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool if y not in x] # here we added condition
    result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates
    for prod in result:
        yield tuple(prod)

来源: https://docs.python.org/3/library/itertools.html#itertools.product

那么结果:

a = [1,2,3]
b = [2,3,4]

for el in product_without_dupl(a,b):
    print(el)

#outputs:
(2, 4)
(1, 2)
(3, 4)
(1, 4)
(2, 3)
(1, 3)