Python:生成列表的所有有序组合

Posted

技术标签:

【中文标题】Python:生成列表的所有有序组合【英文标题】:Python: Generating all ordered combinations of a list 【发布时间】:2015-10-13 09:47:55 【问题描述】:

我使用的是 Python 2.7。

我有一个列表,我想要所有可能的有序组合。

import itertools
stuff = ["a","b","c", "d"]
for L in range(1, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        print( ' '.join(subset))

这将给出以下输出:

a
b
c
d
a b
a c <-- not in correct order
a d <-- not in correct order
b c
b d <-- not in correct order
c d
a b c
a b d <-- not in correct order
a c d <-- not in correct order
b c d
a b c d

但我希望输出仅是与stuff 列表顺序相同的组合。例如。删除 a db da b da c d,因为与 stuff 列表 ["a", "b", "c", "d"] 相比,它们的顺序不正确。

我已经想办法改用这个了:

import itertools
stuff = ["a","b","c", "d"]
for L in range(1, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        if ' '.join(subset) in ' '.join(stuff): #added line
            print( ' '.join(subset))

正在给我想要的输出:

a
b
c
d
a b
b c
c d
a b c
b c d
a b c d

但是 Python 中是否有任何内置方法可以满足我的需求?

【问题讨论】:

为什么a d 的顺序不正确?你是什​​么意思订单?您是否只对原始列表的 slices 感兴趣?为什么a c 的顺序不正确而a d 不正确? 【参考方案1】:

我相信您正在寻找的是您原始列表中所有可能的片段。您想要的转换成切片的输出是这样的:

a         # slices[0:1]
b         # slices[1:2]
c         # slices[2:3]
d         # slices[3:4]
a b       # slices[0:2]
b c       # slices[1:3]
c d       # slices[2:4]
a b c     # slices[0:3]
b c d     # slices[1:4]
a b c d   # slices[0:4]

所以你应该尝试生成的是那些索引。如果你仔细观察并对它们进行排序,你会发现它们是 0 到 4 之间数字的 2 组合,其中第一个数字小于另一个数字——这正是 itertools.combinations 对索引列表所做的。所以我们可以生成这些:

for i, j in itertools.combinations(range(len(stuff) + 1), 2):
    print(stuff[i:j])

这会产生以下输出:

['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['c']
['c', 'd']
['d']

优点是这会产生您输入的实际子列表,而不关心那些首先是单个字符的子列表。它可以是列表中的任何类型的内容。

如果输出顺序很重要,您可以按输出列表大小排序以获得所需的结果:

def getCombinations (lst):
    for i, j in itertools.combinations(range(len(lst) + 1), 2):
        yield lst[i:j]

for x in sorted(getCombinations(stuff), key=len):
    print(' '.join(x))

【讨论】:

优雅的代码。可能需要对最终结果进行排序,就像在示例输出中一样。 @WKPlus 这是一个很好的观点,添加了一种方法来做到这一点。谢谢! :) 如果你使用itertools.combinations而不是itertools.permutations,你可以省略if i &lt; j这一行。 @WKPlus 哦,你是对的。我之前测试过它,但当时没有len + 1 部分,它不工作。猜猜我后来没有再测试它......再次感谢! :)【参考方案2】:

我认为您的意思是“按正确顺序”按连续顺序排列,在这种情况下,您只需要使用两个指向迭代器的指针,而不是 stuff

stuff = ["a","b","c", "d"]
# sort stuff here if it's not sorted

result = []
for i in xrange(len(stuff)):
    for j in xrange(i+1, len(stuff)+1):
        result.append(stuff[i:j])

# sort the result by length, maybe you don't need it
result = sorted(result, key=len)

for r in result:
    print ' '.join(r)

【讨论】:

您可以将 key=lambda x:len(x) 替换为 key=len @TigerhawkT3 是的,它更优雅。 您说得对我认为您的意思是“以正确的顺序”以连续顺序。谢谢你的回复:)

以上是关于Python:生成列表的所有有序组合的主要内容,如果未能解决你的问题,请参考以下文章

如何从Python中列表的dict中的值生成所有组合

python 以随机顺序生成列表的所有组合的字典

如何生成给定列表的幂集?

生成列表的所有可能组合,“itertools.combinations”会遗漏一些结果

组合数据类型,英文词频统计 python

python经典有序序列的list列表推导式实践运用