【问题标题】:Python looping combinations of 8 objects into 3 groups, 3-3-2Python将8个对象组合成3组,3-3-2
【发布时间】:2013-05-02 05:02:25
【问题描述】:

假设我有一个包含 8 个对象的列表,编号为 1-8。

对象被放入三个盒子中,一个盒子里三个,另一个盒子里三个,最后一个盒子里两个。根据数学,有 8C3*5C3=560 种方法可以做到这一点。我想循环浏览 560 个项目。 Python中有什么方法可以做到这一点?

结果应该是这样的:

list=['12','345',678'], ['12','346','578'], ..., etc.

请注意,['12','345','678']['12','354',876'] 在此用途中被视为相同。

我想为这个列表做一个for循环。 Python中有什么方法可以做到这一点?

这是我得到的解决方案,但看起来很难看。

import itertools
for c1,c2 in itertools.combinations(range(8),2):
            l2=list(range(8))
            l2.pop(c2)
            l2.pop(c1)
            for c3,c4,c5 in itertools.combinations(l2,3):
                l3=l2[:]
                l3.remove(c5)
                l3.remove(c4)
                l3.remove(c3)
                c6,c7,c8=l3
                print(c1,c2,c3,c4,c5,c6,c7,c8)

【问题讨论】:

  • 你是怎么解决的?什么代码?
  • 您可以使用 itertools docs.python.org/2/library/itertools.html 并添加一些您自己的逻辑。
  • 我必须说我不太明白你的问题。
  • 那么,你解决了吗?

标签: python list combinations


【解决方案1】:
def F(seq, parts, indexes=None, res=[], cur=0):
    if indexes is None: # indexes to use for combinations
        indexes = range(len(seq))

    if cur >= len(parts): # base case
        yield [[seq[i] for i in g] for g in res]
        return    

    for x in combinations(indexes, r=parts[cur]):
        set_x = set(x)
        new_indexes = [i for i in indexes if i not in set_x]
        for comb in F(seq, parts, new_indexes, res=res + [x], cur=cur + 1):
            yield comb

it = F('12345678', parts=(2,3,3))
for i in range(10):
    print [''.join(g) for g in next(it)]

['12', '345', '678']
['12', '346', '578']
['12', '347', '568']
['12', '348', '567']
['12', '356', '478']
['12', '357', '468']
['12', '358', '467']
['12', '367', '458']
['12', '368', '457']
['12', '378', '456']

另一个例子:

for c in F('1234', parts=(2,2)):
    print [''.join(g) for g in c]

['12', '34']
['13', '24']
['14', '23']
['23', '14']
['24', '13']
['34', '12']

【讨论】:

  • 运行代码时出现 IndexError: list index out of range。
  • 很好的答案,我不明白为什么不赞成!
【解决方案2】:

您可以置换所有 8 个值(如之前的答案所示)。 为此使用此previous answer(也在以下代码中)。

然后将每个组合分配为一个元组,以便它们可以被散列和唯一,因为您必须对它们进行排序,因此它们也可以唯一地进行比较。

def all_perms(elements):
    if len(elements) <=1:
        yield elements
    else:
        for perm in all_perms(elements[1:]):
            for i in range(len(elements)):
                #nb elements[0:1] works in both string and list contexts
                yield perm[:i] + elements[0:1] + perm[i:]


v = [1,2,3,4,5,6,7,8]

a = {}
for i in all_perms(v):
    k = (tuple(sorted([i[0],i[1]])) , tuple(sorted([i[2],i[3],i[4]])) , tuple(sorted([i[5],i[6],i[7]])))

    if k not in a:
        a[k] = [str(i[0])+str(i[1]), str(i[2])+str(i[3])+str(i[4]), str(i[5])+str(i[6]) + str(i[7])]

x = 0
for i in a.values():
    print x, i
    x+=1

对于 8 个值的示例,这给出了 560 种组合。

【讨论】:

  • 他出于某种原因删除了它,现在又回到了问题中
【解决方案3】:

l 将是八个对象的列表,在此示例中为字符串:

l = ["O1","02","03","04","04","06","07","08"]
for group in [l[:3],l[3:6],l[6:]]: #get 3 slices of the list into 3's and a 2
    print(group)

生产:

>>> 
['O1', '02', '03']
['04', '04', '06']
['07','08']

【讨论】:

    猜你喜欢
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    相关资源
    最近更新 更多