Python 组合
Python Combinations
假设我有一个 Python 列表,如下所示:
[1, 2, 3, 4]
我希望能够 return 包含两个或多个数字的所有组合的列表列表。值的顺序无关紧要,因此 1,2 与 2,1 相同。我还想 return 另一个列表,其中包含每个组合中没有的值。例如:
Combination 1,2 / Remainder 3,4
Combination 2,3 / Remainder 1,4
Combination 1,2,3 / Remainder 4
Combination 1,2,3,4/ Remainder -
上述 returned 列表为
combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]]
remainder = [[3,4], [1,4], [4], []]
我只展示了几个例子...
我意识到第一部分可能可以使用 itertools.combinations
来实现,但是我如何 return 那些没有在组合中使用的值而不循环?
您可以取套差:
l = set([1, 2, 3, 4])
for i in range(len(l)+1):
for comb in itertools.combinations(l, i):
print(comb, l.difference(comb))
() {1, 2, 3, 4}
(1,) {2, 3, 4}
(2,) {1, 3, 4}
(3,) {1, 2, 4}
(4,) {1, 2, 3}
(1, 2) {3, 4}
(1, 3) {2, 4}
(1, 4) {2, 3}
(2, 3) {1, 4}
(2, 4) {1, 3}
(3, 4) {1, 2}
(1, 2, 3) {4}
(1, 2, 4) {3}
(1, 3, 4) {2}
(2, 3, 4) {1}
(1, 2, 3, 4) set()
假设你有这个向量 [1 6 3]
您可以生成从 0 到 2^3-1 的所有数字,其中 3 是 len([1 6 3])
0
1
2
3
4
5
6
7
将此数字转换为二进制后:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
将你的向量放在生成的序列的顶部:
[1 6 3]
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
对于每一行,在组合中附加与 1 相同位置的数字,在其余部分附加与 0 位置相同的数字。
因此,例如,查看第 4 行:
Combination: [6,3]
Remainder: [1]
最后:
Combination: [],[3],[6],[6,3],[1],[1,3],[1,6],[1,6,3]
Remainder: [1,6,3],[1,3],[1],[6,3],[6],[3],[]
这里是代码:
vec=[1,3,6]
binary_vec = [format(i,'b').zfill(len(vec)) for i in range(2**len(vec))]
print([[vec[i] for i,y in enumerate(x) if y != "0"] for x in binary_vec])
print([[vec[i] for i,y in enumerate(x) if y == "0"] for x in binary_vec])
输出:
也看看我在这个post中的回答:
基于 的想法,但不是将特定范围内的数字转换为二进制,您可以只使用 itertools.product
来获得 1
和 [= 的所有组合16=] (或 True
和 False
),然后将其用作过滤 "ins" 和 "outs".
的掩码
>>> 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 列表,如下所示:
[1, 2, 3, 4]
我希望能够 return 包含两个或多个数字的所有组合的列表列表。值的顺序无关紧要,因此 1,2 与 2,1 相同。我还想 return 另一个列表,其中包含每个组合中没有的值。例如:
Combination 1,2 / Remainder 3,4
Combination 2,3 / Remainder 1,4
Combination 1,2,3 / Remainder 4
Combination 1,2,3,4/ Remainder -
上述 returned 列表为
combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]]
remainder = [[3,4], [1,4], [4], []]
我只展示了几个例子...
我意识到第一部分可能可以使用 itertools.combinations
来实现,但是我如何 return 那些没有在组合中使用的值而不循环?
您可以取套差:
l = set([1, 2, 3, 4])
for i in range(len(l)+1):
for comb in itertools.combinations(l, i):
print(comb, l.difference(comb))
() {1, 2, 3, 4}
(1,) {2, 3, 4}
(2,) {1, 3, 4}
(3,) {1, 2, 4}
(4,) {1, 2, 3}
(1, 2) {3, 4}
(1, 3) {2, 4}
(1, 4) {2, 3}
(2, 3) {1, 4}
(2, 4) {1, 3}
(3, 4) {1, 2}
(1, 2, 3) {4}
(1, 2, 4) {3}
(1, 3, 4) {2}
(2, 3, 4) {1}
(1, 2, 3, 4) set()
假设你有这个向量 [1 6 3]
您可以生成从 0 到 2^3-1 的所有数字,其中 3 是 len([1 6 3])
0
1
2
3
4
5
6
7
将此数字转换为二进制后:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
将你的向量放在生成的序列的顶部:
[1 6 3]
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
对于每一行,在组合中附加与 1 相同位置的数字,在其余部分附加与 0 位置相同的数字。
因此,例如,查看第 4 行:
Combination: [6,3]
Remainder: [1]
最后:
Combination: [],[3],[6],[6,3],[1],[1,3],[1,6],[1,6,3]
Remainder: [1,6,3],[1,3],[1],[6,3],[6],[3],[]
这里是代码:
vec=[1,3,6]
binary_vec = [format(i,'b').zfill(len(vec)) for i in range(2**len(vec))]
print([[vec[i] for i,y in enumerate(x) if y != "0"] for x in binary_vec])
print([[vec[i] for i,y in enumerate(x) if y == "0"] for x in binary_vec])
输出:
也看看我在这个post中的回答:
基于 itertools.product
来获得 1
和 [= 的所有组合16=] (或 True
和 False
),然后将其用作过滤 "ins" 和 "outs".
>>> 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]))]