【问题标题】:Most efficient way of producing constrained pairs of combinations out of a list in Python从 Python 列表中生成约束组合对的最有效方法
【发布时间】:2019-10-01 11:00:20
【问题描述】:

我需要在 l 的项目列表中迭代长度为 2 的组合的 (a, b)(c, d) 对,并具有以下约束:

  1. 不成对重复:如果(a, b)已经出现,则(b, a)不应产生
  2. 对之间没有重复,即对必须只考虑一次:如果(a, b)(c, d)已经出现,则不应产生(c, d)(a, b)
  3. 两对中的项目必须不同:a != c and a != d and b != c and b != d

例如,用

l = [0, 1, 2, 3, 4]

这对应该是:

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

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

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

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

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

我在示例中使用了整数,但是,我对更通用的解决方案感兴趣(尽管项目是列表,在我的具体情况下)。

这是我想出的解决方案:

import itertools

used = set()

for (a, b) in itertools.combinations(l, 2):
    used.add((a, b))
    for (c, d) in itertools.combinations(l, 2):
        if a == c or a == d or b == c or b == d:
            continue
        if (c, d) in used:
            continue
        # do stuff...
        pass

除了看起来很麻烦之外,这个解决方案还需要额外的集合used。在实际实现中,我使用enumerate(l) 而不是l 并将项目的索引放在集合中的元组中,并尝试使用索引更快地过滤选项......但没有设法使它成为任何更好。

我怎样才能使它更高效,并且可能更优雅/Pythonic?

【问题讨论】:

  • 数字 4 未出现在您的列表中 l。这是正确的吗?
  • 不,不是,我刚刚修好了,谢谢指出!

标签: python list combinations combinatorics


【解决方案1】:

一个想法可能是首先生成元组的所有组合,然后过滤它们:

l = [0, 1, 2, 3, 4]
aa = list(itertools.combinations(list(itertools.combinations(l, 2)), 2))
[(a,b) for a,b in aa if set(a).isdisjoint(b)]

【讨论】:

  • 我喜欢这种方法,并投了票,因为它对我来说是新的。但是,它需要分配两个列表,并且aa 可以很快变大,所以我不相信它在内存中的效率更高。我对吗?是不是更快?
  • 确实,如果 L 很大,内存消耗可能是个问题。另一种选择是在 list(itertools.combinations(l, 2) 上进行双循环,但我不知道如何删除 ((c,d), (a,b)) when ((a,b), (c,d)) 已经存在。如果有人可以用它构建一些东西: [(a,b) for a in a a for b in aa if set(a).isdisjoint(b)] where aa = list(itertools. combination(l, 2). aa 在这种情况下要小得多。
猜你喜欢
  • 2019-10-23
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 2017-10-13
  • 1970-01-01
  • 2012-05-17
相关资源
最近更新 更多