假设我有一个如下所示的 Python 列表:
[1, 2, 3, 4]
我希望能够返回包含两个或多个数字的所有组合的列表列表。值的顺序无关紧要,因此 1,2 与 2,1 相同。我还想返回另一个列表,其中包含每个组合中没有的值。例如:
Combination 1,2 / Remainder 3,4
Combination 2,3 / Remainder 1,4
Combination 1,2,3 / Remainder 4
Combination 1,2,3,4/ Remainder -
上面的返回列表是
combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]]
remainder = [[3,4], [1,4], [4], []]
我只展示了几个例子......
我意识到第一部分可能可以使用 itertools.combinations
来实现,但是我如何在不循环的情况下返回组合中未使用的那些值?
最佳答案
基于 Nunzio 的想法,但不是将特定范围内的数字转换为二进制,您可以只使用 itertools.product
来获取 1
和的所有组合0
(或 True
和 False
),然后将其用作过滤“输入”和“输出”的掩码。
>>> lst = [1,2,3]
>>> products = list(product([1,0], repeat=len(lst)))
>>> [[lst[i] for i, e in enumerate(p) if e] for p in products]
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
>>> [[lst[i] for i, e in enumerate(p) if not e] for p in products]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
您还可以为该enumerate
理解定义一个函数,并一次性完成这两个部分:
>>> mask = lambda lst, p, v: [lst[i] for i, e in enumerate(p) if e == v]
>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0], repeat=len(lst))]
[([1, 2, 3], []),
([1, 2], [3]),
([1, 3], [2]),
([1], [2, 3]),
([2, 3], [1]),
([2], [1, 3]),
([3], [1, 2]),
([], [1, 2, 3])]
如果您只想与“in”列表中的 2 个或更多个组合,您可以添加一个条件:
>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0],repeat=len(lst)) if sum(p) >= 2]
或者使用 numpy
数组并利用 numpy
的高级索引:
>>> arr = np.array([1,2,3])
>>> [(arr[p==1], arr[p==0]) for p in map(np.array, product([1,0], repeat=len(arr)))]
[(array([1, 2, 3]), array([])),
(array([1, 2]), array([3])),
(array([1, 3]), array([2])),
(array([1]), array([2, 3])),
(array([2, 3]), array([1])),
(array([2]), array([1, 3])),
(array([3]), array([1, 2])),
(array([]), array([1, 2, 3]))]
关于Python组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39545543/