将组合结果分组到包含子列表的列表中

时间:2018-01-05 19:44:28

标签: python python-3.x list combinations itertools

我有列表a

a = [0,1,2,3,4,5]

然后我创建此列表的所有三元素组合。结果在子列表中分组,因为它以二进制3位字符串的形式与等效项匹配。例如,结果[0,4,5]对应于序列001,因为每个偶数对应于0,奇数对应于。

我与评论一起使用的代码:

import itertools as it
import itertools

# I create three-element combinations of zeros and ones
combinations_3bit = list(map(list, itertools.product([0,1], repeat=3)))
# output: [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]

# I create a list of strings with values from the list `3bit_combinations`
a=[]
for i in range(len(combinations_3bit)):
    a2 =''.join(map(str, [1 if x%2 else 0 for x in combinations_3bit[i]]))
    a.append(a2)
# output: ['000', '001', '010', '011', '100', '101', '110', '111'] 

# I remove repetitions in pairs of type 001 with 100, 011 with 110, etc.
combinations_3bit_without_repetition = [v for k, v in enumerate(a) if v[::-1] not in a[:k]] 
# output: ['000', '001', '010', '011', '101', '111'] 

b = [0,1,2,3,4,5]

good = []
for i in range(len(combinations_3bit_without_repetition)):
    c=[]
    for u in it.combinations(b, 3):       
        u1 = list(u)                  
        y =''.join(map(str, [1 if x%2 else 0 for x in u1]))
        if y == combinations_3bit_without_repetition[i]:
           c.append(u1)
    good.append(c) 

# output: [[[0, 2, 4]], [[0, 2, 3], [0, 2, 5], [0, 4, 5], [2, 4, 5]], [[0, 1, 2], [0, 1, 4], [0, 3, 4], [2, 3, 4]], [[0, 1, 3], [0, 1, 5], [0, 3, 5], [2, 3, 5]], [[1, 2, 3], [1, 2, 5], [1, 4, 5], [3, 4, 5]], [[1, 3, 5]]]

这可以更好,更经济地解决吗? 因为上面的解决方案似乎是“周围”,例如函数it.combinations在列表i中的每个索引combinations_3bit_without_repetition之后返回所有可能的组合,然后条件仅筛选匹配那些。对于大型列表,此解决方案很弱;)

2 个答案:

答案 0 :(得分:3)

有一种更好的方法可以生成所需的二进制字符串:

import itertools

strings = ['{0:03b}'.format(i) for i in range(8)]
b = [0,1,2,3,4,5]
combinations = [list(x) for x in itertools.combinations(b, 3)]

dct = {}

for x in combinations:
  y = ''.join(str(j%2) for j in x)
  if y in dct:
    dct[y].append(x)
  else:
    dct[y] = [x]

print(dct)

输出:

{'010': [[0, 1, 2], [0, 1, 4], [0, 3, 4], [2, 3, 4]], '011': [[0, 1, 3], [0, 1, 5], [0, 3, 5], [2, 3, 5]], '001': [[0, 2, 3], [0, 2, 5], [0, 4, 5], [2, 4, 5]], '000': [[0, 2, 4]], '101': [[1, 2, 3], [1, 2, 5], [1, 4, 5], [3, 4, 5]], '100': [[1, 2, 4]], '110': [[1, 3, 4]], '111': [[1, 3, 5]]}

检查这是否符合您的需要。它创建一个字典,其中每个键都是长度为3的二进制字符串,每个值都是与二进制字符串匹配的组合数组。

答案 1 :(得分:2)

以下是使用itertools.groupbyb的{​​{1}}解决方案:

combinations_3bit_without_repetition

打印:

def binarize(x):
    return ''.join(map(str, map((1).__and__, x)))

srted = sorted(itertools.combinations(b, 3), key=binarize)
allowed = set(combinations_3bit_without_repetition)
result = [list(grp) for bn, grp in itertools.groupby(srted, binarize) if bn in allowed]

print(result)