【问题标题】:How to generate itertools product without duplicates?如何生成没有重复的 itertools 产品?
【发布时间】:2020-11-29 08:09:19
【问题描述】:

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

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

但我有一些不同。例如:

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')]

结果:

我不想要 add(a,a),因为第一个值 == 第二个值

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

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

我不能使用组合,因为:

product(['add', 'sub', 1,2,3, 'a','b', 'c'], repeat=3) 与 product(['add', 'sub' ], [2,3, 'a', 'b'], [1,3, 'a', 'c'])

product(['add', 'sub', 1,2,3, 'a','b', 'c'], repeat=3) 中的某些东西不适合我。

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

有人可以帮忙吗?

【问题讨论】:

标签: python product itertools


【解决方案1】:

您可以采用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)

【讨论】:

    【解决方案2】:

    应该这样做:

    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)
    

    【讨论】:

      【解决方案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)
      
      

      我认为这就是你想要做的。

      【讨论】:

      • 哦,我以为你想要他们俩对不起,我会编辑答案
      猜你喜欢
      • 1970-01-01
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 2011-05-08
      • 1970-01-01
      • 2015-01-21
      相关资源
      最近更新 更多