Python中数学函数的标准模块math可以用来计算阶乘。SciPy也有函数来计算排列组合的总数。
itertools模块也可以用来从列表(数组)等中生成排列组合,并对其进行枚举。
这里解释一下,并附有示例代码。
- 系数:
math.factorial()
- 计算排列组合的总数
math.factorial()
scipy.special.perm()
- 从一个列表中生成和列举排列组合:
itertools.permutations()
- 计算组合的总数量
math.factorial()
scipy.special.comb()
- 如何不使用math.factorial()?
- 从列表中生成和列举组合:
itertools.combinations()
- 计算出重复组合的总数量
- 从列表中生成并列举出重复的组合:
itertools.combinations_with_replacement()
作为利用排列组合的一个例子,下面还将解释。
- 从字符串中创造一个个字母
如果你想生成多个列表的元素组合,而不是单一的列表,请使用itertools模块中的itertools.product()。
系数: math.factorial()
数学模块提供了一个函数 factorial(),用于返回阶乘。
import math
print(math.factorial(5))
# 120
print(math.factorial(0))
# 1
非整数、负值将导致一个ValueError。
# print(math.factorial(1.5))
# ValueError: factorial() only accepts integral values
# print(math.factorial(-1))
# ValueError: factorial() not defined for negative values
计算排列组合的总数
math.factorial()
排列是指从n个不同的中选取r并放在一行中的情况的数量。
使用阶乘的方式,通过以下公式得到排列组合的总数p。
p = n! / (n - r)!
可以用函数math.factorial()进行如下计算,它返回阶乘。⌘运算符,执行整数除法,用于返回一个整数类型。
def permutations_count(n, r):
return math.factorial(n) // math.factorial(n - r)
print(permutations_count(4, 2))
# 12
print(permutations_count(4, 4))
# 24
scipy.special.perm()
SciPy提供了一个函数scipy.special.perm()来返回排列组合的总数。需要单独安装SciPy。从0.14.0版本开始提供。
from scipy.special import perm
print(perm(4, 2))
# 12.0
print(perm(4, 2, exact=True))
# 12
print(perm(4, 4, exact=True))
# 24
exact=False
第三个参数默认设置如上,返回一个浮点数。请注意,如果你想得到的是一个整数,你需要按以下方式设置它。exact=True
注意,只有 “import scipy “不会加载scipy.special模块。
像上面的例子一样,将perm()执行为 “from scipy.special import perm”,或者将scipy.special.perm()执行为 “import scipy.special”。
从一个列表中生成和列举排列组合: itertools.permutations()
不仅是总数,还可以从列表(数组)中生成和列举排列组合,等等。
使用itertools模块的permutations()函数。
传递一个迭代器(列表或集合类型)作为第一个参数,传递要选择的件数作为第二个参数,就会返回一个该排列组合的迭代器。
import itertools
l = ['a', 'b', 'c', 'd']
p = itertools.permutations(l, 2)
print(type(p))
# <class 'itertools.permutations'>
要列举所有这些,你可以使用for循环。
for v in itertools.permutations(l, 2):
print(v)
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'a')
# ('b', 'c')
# ('b', 'd')
# ('c', 'a')
# ('c', 'b')
# ('c', 'd')
# ('d', 'a')
# ('d', 'b')
# ('d', 'c')
由于它是一个有限的迭代器,它也可以用list()转换为一个列表类型。
当用len()得到列表中的元素数时,可以确认它与由阶乘计算出的排列组合总数相匹配。
p_list = list(itertools.permutations(l, 2))
print(p_list)
# [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'a'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('c', 'd'), ('d', 'a'), ('d', 'b'), ('d', 'c')]
print(len(p_list))
# 12
如果省略第二个参数,将返回选择所有元素的排列组合。
for v in itertools.permutations(l):
print(v)
# ('a', 'b', 'c', 'd')
# ('a', 'b', 'd', 'c')
# ('a', 'c', 'b', 'd')
# ('a', 'c', 'd', 'b')
# ('a', 'd', 'b', 'c')
# ('a', 'd', 'c', 'b')
# ('b', 'a', 'c', 'd')
# ('b', 'a', 'd', 'c')
# ('b', 'c', 'a', 'd')
# ('b', 'c', 'd', 'a')
# ('b', 'd', 'a', 'c')
# ('b', 'd', 'c', 'a')
# ('c', 'a', 'b', 'd')
# ('c', 'a', 'd', 'b')
# ('c', 'b', 'a', 'd')
# ('c', 'b', 'd', 'a')
# ('c', 'd', 'a', 'b')
# ('c', 'd', 'b', 'a')
# ('d', 'a', 'b', 'c')
# ('d', 'a', 'c', 'b')
# ('d', 'b', 'a', 'c')
# ('d', 'b', 'c', 'a')
# ('d', 'c', 'a', 'b')
# ('d', 'c', 'b', 'a')
print(len(list(itertools.permutations(l))))
# 24
在itertools.permutations()中,元素的处理是基于位置,而不是价值。重复的值不会被考虑在内。
l = ['a', 'a']
for v in itertools.permutations(l, 2):
print(v)
# ('a', 'a')
# ('a', 'a')
这同样适用于以下功能,如下所述。
itertools.combinations()
itertools.combinations_with_replacement()
计算组合的总数量
math.factorial()
组合的数量是指从n个不同的棋子中选择r个棋子的数量。顺序并不像排列组合那样被考虑。
组合的总数c由以下公式得到。
c = n! / (r! * (n - r)!)
可以用函数math.factorial()进行如下计算,它返回阶乘。⌘运算符,执行整数除法,用于返回一个整数类型。
def combinations_count(n, r):
return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))
print(combinations_count(4, 2))
# 6
scipy.special.comb()
SciPy提供了一个函数scipy.special.comb()来返回排列组合的总数。需要单独安装SciPy。从0.14.0版本开始提供。注意,scipy.misc.comb()没有实现下面描述的参数重复。
from scipy.special import comb
print(comb(4, 2))
# 6.0
print(comb(4, 2, exact=True))
# 6
print(comb(4, 0, exact=True))
# 1
exact=False
和scipy.special.perm()一样,第三个参数默认设置为上述参数,返回一个浮点数。注意,如果你想得到它是一个整数,你需要按如下方法设置它。exact=True
重复组合的总数也可以通过第四个参数,即重复来获得。这将在下面描述。
再次注意,只有 “import scipy “不会加载scipy.special模块。
如上面的例子,执行 comb() 为 “from scipy.special import comb” 或执行 scipy.special.comb() 为 “import scipy.special” 。这同样适用于 “scipy.misc”。
如何不使用math.factorial()?
另一个只使用标准库的方法,比使用math.factorial()的方法更快,是以下方法。
from operator import mul
from functools import reduce
def combinations_count(n, r):
r = min(r, n - r)
numer = reduce(mul, range(n, n - r, -1), 1)
denom = reduce(mul, range(1, r + 1), 1)
return numer // denom
print(combinations_count(4, 2))
# 6
print(combinations_count(4, 0))
# 1
从列表中生成和列举组合: itertools.combinations()
可以从列表(数组)等中生成和列举所有的组合,也可以生成和列举总数字。
使用itertools模块的combinations()函数。
传递一个迭代器(列表或集合类型)作为第一个参数,传递要选择的件数作为第二个参数,返回该组合的迭代器。
l = ['a', 'b', 'c', 'd']
c = itertools.combinations(l, 2)
print(type(c))
# <class 'itertools.combinations'>
for v in itertools.combinations(l, 2):
print(v)
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'c')
# ('b', 'd')
# ('c', 'd')
c_list = list(itertools.combinations(l, 2))
print(c_list)
# [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
print(len(c_list))
# 6
计算出重复组合的总数量
重复组合的数量是指在允许重复的情况下,从n个不同的组合中选择r的数量。
重复组合的总数等于从(n + r – 1)个不同的组合中选择(r)个组合。
因此,我们可以使用上面定义的函数来计算组合的总数。
def combinations_with_replacement_count(n, r):
return combinations_count(n + r - 1, r)
print(combinations_with_replacement_count(4, 2))
# 10
在上面描述的 “scipy.special.comb() “中,通过设置第四个参数 “repetition=True “可以获得重复组合的总数。
注意,在 “SciPy0.14.0 “之前的版本中,”scipy.misc.comb() “没有实现参数 “重复”。
from scipy.special import comb
print(comb(4, 2, exact=True, repetition=True))
# 10
从列表中生成并列举出重复的组合: itertools.combinations_with_replacement()
可以从列表(数组)等中生成和列举所有重复的组合,也可以生成和列举总数。
使用itertools模块中的combinations_with_replacement()函数。
传递一个迭代器(列表或集合类型)作为第一个参数,传递要选择的件数作为第二个参数,返回该重叠组合的一个迭代器。
h = itertools.combinations_with_replacement(l, 2)
print(type(h))
# <class 'itertools.combinations_with_replacement'>
for v in itertools.combinations_with_replacement(l, 2):
print(v)
# ('a', 'a')
# ('a', 'b')
# ('a', 'c')
# ('a', 'd')
# ('b', 'b')
# ('b', 'c')
# ('b', 'd')
# ('c', 'c')
# ('c', 'd')
# ('d', 'd')
h_list = list(itertools.combinations_with_replacement(l, 2))
print(h_list)
# [('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'b'), ('b', 'c'), ('b', 'd'), ('c', 'c'), ('c', 'd'), ('d', 'd')]
print(len(h_list))
# 10
从字符串中创造一个个字母
Itertools.permutations()可以很容易地创建字符串的排列组合(agrams)。
s = 'arc'
for v in itertools.permutations(s):
print(v)
# ('a', 'r', 'c')
# ('a', 'c', 'r')
# ('r', 'a', 'c')
# ('r', 'c', 'a')
# ('c', 'a', 'r')
# ('c', 'r', 'a')
要将一次一个字符的元组合并成一个字符串,并使其成为一个列表,请执行以下操作
anagram_list = [''.join(v) for v in itertools.permutations(s)]
print(anagram_list)
# ['arc', 'acr', 'rac', 'rca', 'car', 'cra']
join()方法将一个列表或元组的元素连接成一个字符串,并使用了列表理解符号。