如何计算我可以用多少种不同的方式在python中对列表排序
我对如何做到这一点有点困惑,我知道这可能也需要一些概率知识(我缺乏) 我如何计算有多少种方式,并获得所有的可能性,有多少种方式我可以订购一个列表如何计算我可以用多少种不同的方式在python中对列表排序,python,probability,Python,Probability,我对如何做到这一点有点困惑,我知道这可能也需要一些概率知识(我缺乏) 我如何计算有多少种方式,并获得所有的可能性,有多少种方式我可以订购一个列表 例如,如果我有lst=[“a”、“a”、“a”、“b”、“b”、“b”],我可以用多少种方式来订购此产品/如何获得所有可能的组合?我一直在查看itertools,但没有找到相关内容。您可以使用permutations()获取所有排列,并使用set()删除重复项: >>> from itertools import permutatio
例如,如果我有
lst=[“a”、“a”、“a”、“b”、“b”、“b”]
,我可以用多少种方式来订购此产品/如何获得所有可能的组合?我一直在查看itertools
,但没有找到相关内容。您可以使用permutations()
获取所有排列,并使用set()
删除重复项:
>>> from itertools import permutations
>>> set(permutations(lst))
{('b', 'a', 'b', 'a', 'a', 'a', 'b'), ('b', 'a', 'a', 'b', 'a', 'a', 'b'), ('b', 'a', 'a', 'b', 'b', 'a', 'a'), ('a', 'a', 'b', 'b', 'a', 'a', 'b'), ('a', 'a', 'b', 'a', 'b', 'b', 'a'), ('b', 'b', 'a', 'b', 'a', 'a', 'a'), ('b', 'a', 'a', 'a', 'b', 'a', 'b'), ('b', 'a', 'b', 'a', 'b', 'a', 'a'), ('b', 'b', 'a', 'a', 'b', 'a', 'a'), ('b', 'b', 'b', 'a', 'a', 'a', 'a'), ('a', 'a', 'a', 'b', 'a', 'b', 'b'), ('a', 'a', 'b', 'b', 'b', 'a', 'a'), ('a', 'a', 'a', 'b', 'b', 'b', 'a'), ('a', 'b', 'b', 'a', 'a', 'b', 'a'), ('b', 'a', 'b', 'b', 'a', 'a', 'a'), ('a', 'b', 'b', 'b', 'a', 'a', 'a'), ('a', 'b', 'a', 'a', 'a', 'b', 'b'), ('a', 'b', 'a', 'b', 'a', 'b', 'a'), ('a', 'b', 'b', 'a', 'a', 'a', 'b'), ('a', 'b', 'b', 'a', 'b', 'a', 'a'), ('a', 'a', 'b', 'a', 'b', 'a', 'b'), ('a', 'b', 'a', 'b', 'b', 'a', 'a'), ('b', 'b', 'a', 'a', 'a', 'b', 'a'), ('a', 'a', 'b', 'a', 'a', 'b', 'b'), ('a', 'a', 'a', 'a', 'b', 'b', 'b'), ('b', 'a', 'b', 'a', 'a', 'b', 'a'), ('b', 'b', 'a', 'a', 'a', 'a', 'b'), ('a', 'b', 'a', 'a', 'b', 'b', 'a'), ('b', 'a', 'a', 'b', 'a', 'b', 'a'), ('a', 'a', 'a', 'b', 'b', 'a', 'b'), ('a', 'b', 'a', 'a', 'b', 'a', 'b'), ('a', 'a', 'b', 'b', 'a', 'b', 'a'), ('a', 'b', 'a', 'b', 'a', 'a', 'b'), ('b', 'a', 'a', 'a', 'a', 'b', 'b'), ('b', 'a', 'a', 'a', 'b', 'b', 'a')}
>>>
请注意,他的方法不是一种优化方法,因为它首先计算所有置换,尽管它返回一个迭代器,并且不会将所有置换都存储在内存中,但这仍然不是最好的方法,如果您处理的是非大型数据集,这就很好了
如果您想使用优化的方法,您可以自定义
置换
的等效函数。正如Kasramvd提到的,使用itertools。置换
不是生成包含重复元素的列表置换的有效方法。示例数据有7个元素,因此itertools.permutations
生成7!=5040个排列,但只有35个=唯一排列
幸运的是,14世纪的印度数学家纳拉亚娜·潘迪塔(Narayana Pandita)提出了一种古老的排列算法,该算法以字典顺序生成排列,能够优雅地处理重复的元素。下面是一个描述(来源于文章),展示了该算法如何从当前置换生成下一个置换
def lexico_permute(a):
a = list(a)
yield a
n = len(a) - 1
while True:
for j in range(n-1, -1, -1):
if a[j] < a[j + 1]:
break
else:
return
v = a[j]
for k in range(n, j, -1):
if v < a[k]:
break
a[j], a[k] = a[k], a[j]
a[j+1:] = a[j+1:][::-1]
yield a
# Test
lst = ["a", "a", "a", "a", "b", "b", "b"]
for i, u in enumerate(lexico_permute(lst), 1):
print(i, u)
FWIW,对于问题中给出的列表,该代码比使用set(排列(lst))
快8倍左右;对于较大的输入列表,可以节省更多的时间
lexico\u permute
最初从输入序列(也可以是元组、字符串等)生成一个新列表。然后,它生成新列表,将其推进到下一个置换,然后再次生成相同的列表。因此,如果您只是将其输出附加到一个空列表,那么您将得到一个列表列表,该列表仅包含对同一列表的多个引用。这通常不是很有用。:)
解决这个问题的简单方法是附加一个由lexico\u permute
生成的列表副本,例如
all_perms = []
for u in lexico_permute(lst):
all_perms.append(u[:])
或作为列表:
all_perms = [u[:] for u in lexico_permute(lst)]
或者,将lexico\u permute
中的两个yield语句更改为
yield a[:]
然后你就可以做了
all_perms = list(lexico_permute(lst))
听起来你只是在计算可区分排列的数量,而不是生成它们 如果有一种类型的n1个不可区分元素,另一种类型的n2个不可区分元素,直到最后一种类型的nk个元素,那么集合的不可区分排列数的公式为: 要在Python中计算此值,我们可以执行以下操作:
from collections import Counter
from math import factorial
from functools import reduce
import operator
def unique_permutations(lst):
c = Counter(lst)
return factorial(len(lst)) // reduce(operator.mul, map(factorial, c.values()))
以下是输出:
>>> unique_permutations(["a", "a", "a", "a", "b", "b", "b"])
35
排序数:
数学阶乘(len(lst))
(函数)。可能的排列顺序:itertools.permutations(lst)
@sascha:该公式不考虑重复元素。@PM2Ring他对该要求做了任何声明吗?@sascha没有明确说明,但从上下文来看,OP不希望重复排列。否则,他将只使用itertools.permutations
。值得注意的是,随着列表变长,这将需要大量内存来同时存储所有可能的组合。@Josh不,permutations返回一个迭代器对象,但这仍然不是一种优化方法,至少在运行时方面是如此。但这是一个快速的方法<代码>置换确实返回迭代器对象,但将其转换为集合会将迭代器返回的每个元素复制到内存中。@Josh迭代器是一次性的可重用对象,因此当您将迭代器转换为类似集合或列表的可重用对象时,python会将项目逐个传递到目标对象。它实际上相当于set(迭代器中的i代表i)
,因此我们不会同时在内存中存储所有这些重复项,因为set()
不存储它们。@Josh:也许你误解了Kasra。当然,集合存储了所有的唯一项,但在任何时候都不会存储在内存中的所有排列。因此,使用OP的lst
,置换
生成器生成5040个元组,这些元组在生成时一次添加一个到集合中。任何重复的都会被拒绝,所以集合中包含的元组不会超过35个。感谢您提供的伟大的备选答案。我有一个简短的(可能是愚蠢的)问题。在最后一行中,我没有打印(i,u),而是将它们附加到一个空列表中,这样我就可以得到一个列表列表。然而,一旦我这样做了,我所做的就是得到原始“lst”变量的重复。在您的示例中,您知道有什么东西可以阻止追加正常发生吗?@tzhu10对此表示抱歉。我很快会在回答中添加更多信息。
>>> unique_permutations(["a", "a", "a", "a", "b", "b", "b"])
35