如何在 Python 中,独立于该列表中元素的类型生成列表的所有的排列?

例如︰

permutations([])
[]

permutations([1])
[1]

permutations([1, 2])
[1, 2]
[2, 1]

permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

编辑︰ Eliben 指向一个类似来挖掘虽然简单,所以我选择它作为接受的答案,尽管 Python 2.6 + itertools模块中有一个内置的解决方案的解决方案︰

import itertools
itertools.permutations([1, 2, 3])
2008-09-19 18:41:03
问题评论:

或许应考虑指出,您的问题是关于 Python 2.5

我同意与递归,接受答案的今天。但是,这仍然挂起那里作为一个巨大的计算机科学的问题。接受的答案解决了此问题具有指数的复杂性 (2 ^ N N=len(list)) 解决此问题 (或证明不能) 在多项式时间:)请参阅"旅行商问题"

@FlipMcF 将会很难,"解决方法"在多项式时间内,提供其所需的阶乘时间甚至只是列举输出...,不,不可能。

回答:

从 Python 2.6(并且您是 Python 3) 您对此有一个标准库的工具︰ itertools.permutations .


如果您使用的旧 Python (< 2.6)的一些原因或只是好奇,了解它的工作原理,下面是从http://code.activestate.com/recipes/252178/而采取的一个很好的做法:

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:]

itertools.permutations的文档中列出了几种替代方法。这里就有一个︰

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = range(n)
    cycles = range(n, n-r, -1)
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return

而另一种基于itertools.product:

def permutations(iterable, r=None):
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    for indices in product(range(n), repeat=r):
        if len(set(indices)) == r:
            yield tuple(pool[i] for i in indices)

这和其他递归解决方案具有潜在危险的耗尽了所有的 RAM,如果足够大排列后的列表

使用大型列表也达到递归限制 (和凹模)

bgbg,dbr︰ 它使用一个生成器,因此函数本身不会用光内存。您如何使用迭代器返回的 all_perms (比如无法写入磁盘的每次迭代并不担心有关内存) 其左侧。我知道这篇文章是旧,但我撰写此以便让获得利益立即读取它的所有人。此外现在,最好的方法是使用 itertools.permutations(),正如所指出的很多。

不只是台发电机。它使用嵌套的生成器,其中每个不清楚的情况下将控制权转交给沿调用堆栈进行调试前, 一个。它使用 o (n) 内存,这是很好。

PS︰ 我中修复它的for i in range(len(elements))而不是for i in range(len(elements)+1)事实上,该意见出元素elements[0:1]可以在len(elements)中的不同位置,结果没有len(elements)+1.

并在此后Python 2.6 :

import itertools
itertools.permutations([1,2,3])

(作为一台发电机。使用list(permutations(l))以列表的形式返回。

也适用在 Python 3

下面的代码使用 Python 2.6 和上面只

首先,导入itertools:

import itertools

排列 (顺序方面)︰

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
(2, 1), (2, 3), (2, 4),
(3, 1), (3, 2), (3, 4),
(4, 1), (4, 2), (4, 3)]

组合 (顺序并不重要)︰

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

笛卡儿积 (有几个 iterables):

print list(itertools.product([1,2,3], [4,5,6]))
[(1, 4), (1, 5), (1, 6),
(2, 4), (2, 5), (2, 6),
(3, 4), (3, 5), (3, 6)]

笛卡儿积 (带 iterable 1 和本身)︰

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]

获得使用"列表" TypeError: 'itertools.permutations' object is not callable与"元组",但它确定。这是为什么?

我没有这个问题。检查语法。

+ 1 !文档链接︰ docs.python.org/2/library/itertools.html#itertools.permutations

def permutations(head, tail=''):
    if len(head) == 0: print tail
    else:
        for i in range(len(head)):
            permutations(head[0:i] + head[i+1:], tail+head[i])

作为调用︰

permutations('abc')

此解决方案实现的生成器,以避免所有排列都着内存︰

def permutations (orig_list):
    if not isinstance(orig_list, list):
        orig_list = list(orig_list)

    yield orig_list

    if len(orig_list) == 1:
        return

    for n in sorted(orig_list):
        new_list = orig_list[:]
        pos = new_list.index(n)
        del(new_list[pos])
        new_list.insert(0, n)
        for resto in permutations(new_list[1:]):
            if new_list[:1] + resto <> orig_list:
                yield new_list[:1] + resto
请输入您的翻译

How to generate all permutations of a list in Python

确认取消