FMc*_*FMc 10 python python-itertools cross-product
我想这是一个学术问题,但第二个结果对我来说没有意义.它不应该像第一个一样彻底空洞吗?这种行为的理由是什么?
from itertools import product
one_empty = [ [1,2], [] ]
all_empty = []
print [ t for t in product(*one_empty) ] # []
print [ t for t in product(*all_empty) ] # [()]
Run Code Online (Sandbox Code Playgroud)
更新
感谢所有的答案 - 非常有用.
维基百科对Nullary Cartesian产品的讨论提供了一个明确的陈述:
没有集合的笛卡尔积......是包含空元组的单例集.
from itertools import product
def tproduct(*xss):
return ( sum(rs, ()) for rs in product(*xss) )
def tup(x):
return (x,)
xs = [ [1, 2], [3, 4, 5] ]
ys = [ ['a', 'b'], ['c', 'd', 'e'] ]
txs = [ map(tup, x) for x in xs ] # [[(1,), (2,)], [(3,), (4,), (5,)]]
tys = [ map(tup, y) for y in ys ] # [[('a',), ('b',)], [('c',), ('d',), ('e',)]]
a = [ p for p in tproduct( *(txs + tys) ) ]
b = [ p for p in tproduct( tproduct(*txs), tproduct(*tys) ) ]
assert a == b
Run Code Online (Sandbox Code Playgroud)
sth*_*sth 10
从数学的角度来看,无任何元素的产品应该产生操作产品的中性元素,无论是什么.
例如,对于整数,乘法的中性元素是1,因为对于所有整数a,1·a = a.所以整数的空积应该是1.当实现一个返回数字列表产品的python函数时,这自然会发生:
def iproduct(lst):
result = 1
for i in lst:
result *= i
return result
Run Code Online (Sandbox Code Playgroud)
要使用此算法计算正确的结果,result需要初始化1.这导致1在空列表上调用函数时的返回值.
对于函数而言,此返回值也非常合理.如果您首先连接两个列表然后构建元素的产品,或者如果您首先构建两个单独列表的产品然后乘以结果,那么使用良好的产品功能并不重要:
iproduct(xs + ys) == iproduct(xs) * iproduct(ys)
Run Code Online (Sandbox Code Playgroud)
如果xs或者ys为空则仅在以下情况下有效iproduct([]) == 1.
现在product()迭代器上的复杂程度越来越高.从数学的角度来看,这也product([])应该返回该操作的中性元素,无论是什么.这是不是[]因为product([], xs) == [],而对于中性元素product([], xs) == xs应该持有.事实证明,这[()]也不是一个中性元素:
>>> list(product([()], [1,2,3]))
[((), 1), ((), 2), ((), 3)]
Run Code Online (Sandbox Code Playgroud)
事实上,product()根本不是一个非常好的数学产品,因为上面的等式不成立:
product(*(xs + ys)) != product(product(*xs), product(*ys))
Run Code Online (Sandbox Code Playgroud)
每个产品应用程序都会生成一个额外的元组层,并且没有办法解决这个问题,因此甚至不可能存在真正的中性元素.[()]虽然它非常接近,它不会添加或删除任何元素,它只是为每个元素添加一个空元组.
[()]事实上,这个稍微适应的产品函数的中性元素只能在元组列表上运行,但不会在每个应用程序上添加额外的元组层:
def tproduct(*xss):
# the parameters have to be lists of tuples
return (sum(rs, ()) for rs in product(*xss))
Run Code Online (Sandbox Code Playgroud)
对于此功能,上述产品等式成立:
def tup(x): return (x,)
txs = [map(tup, x) for x in xs]
tys = [map(tup, y) for y in ys]
tproduct(*(txs + tys)) == tproduct(tproduct(*txs), tproduct(*tys))
Run Code Online (Sandbox Code Playgroud)
通过将输入列表打包到元组中的附加预处理步骤,tproduct()给出了相同的结果product(),但从数学的角度来看表现更好.它的中性元素是[()],
因此[()],作为这种列表乘法的中性元素是有道理的.即使它不完全适合product()它也是这个函数的一个很好的选择,因为它允许定义tproduct()而不需要为空输入引入特殊情况.