2013-07-20 19 views
1

在Python中,如何在不使用遞歸和不使用itertools包的情況下編寫一個通用函數來生成重複n次的相同集的笛卡爾乘積?該函數應該有兩個參數:set和n次。Python中的笛卡爾積通用函數

如:

set1={'a','b'} 
print({(x,y) for x in set1 for y in set1}) 

{('a', 'b'), ('b', 'a'), ('b', 'b'), ('a', 'a')} 

print({(x,y,z) for x in set1 for y in set1 for z in set1}) 

{('b', 'a', 'b'), ('a', 'b', 'a'), ('a', 'a', 'a'), ('b', 'a', 'a'), ('a', 'a', 'b'), ('b', 'b', 'a'), ('b', 'b', 'b'), ('a', 'b', 'b')} 

但也:

set2={'a','b','c'} 
print({(x,y,z) for x in set2 for y in set2 for z in set2}) 
print({(w,x,y,z) for w in set2 for x in set2 for y in set2 for z in set2}) 

+0

爲什麼你不能用'itertools'?這是功課嗎? – Blender

+0

沒有itertools ...你用numpy好嗎? – roippi

回答

2

你可以概括你已經通過反覆使用基於理解,技術建立結果:

def cartesian_product(s, dim): 
     if dim == 0: 
      return set() 
     res = [(e,) for e in s] 
     for i in range(dim - 1): 
      res = [e + (f,) for e in res for f in s] 
     return set(res) 

    ex = {1,2,3} 

    for i in range(4): 
     print cartesian_product(ex, i) 

輸出:

set([]) 
set([(2,), (3,), (1,)]) 
set([(1, 2), (3, 2), (1, 3), (3, 3), (3, 1), (2, 1), (2, 3), (2, 2), (1, 1)]) 
set([(1, 3, 2), (1, 3, 1), (3, 3, 1), (2, 3, 1), (3, 3, 3), (2, 3, 2), (3, 3, 2), (2, 3, 3), (3, 2, 2), (3, 1, 3), (3, 2, 3), (3, 1, 2), (1, 2, 1), (3, 1, 1), (3, 2, 1), (1, 2, 2), (1, 2, 3), (1, 1, 1), (2, 1, 2), (2, 2, 3), (2, 1, 3), (2, 2, 2), (2, 2, 1), (2, 1, 1), (1, 1, 2), (1, 1, 3), (1, 3, 3)]) 
+0

這正是我所尋找的,也讓我意識到在Python中,單元素元組需要一個尾隨逗號。 – Javide

1
def cartesian(A,n): 
    tmp1,tmp2 = [],[[]] 
    for k in range(n): 
     for i in A: 
      tmp1.extend([j+[i] for j in tmp2]) 
     tmp1,tmp2 = [],tmp1 
    return tmp2 

[In:1] A = [1,2,3] ; n = 1 
[Out:1] [[1], [2], [3]] 

[In:2] A = [1,2,3] ; n = 4 
[Out:2] [[1, 1, 1], [2, 1, 1], [3, 1, 1], [1, 2, 1], [2, 2, 1], [3, 2, 1], [1, 3, 1], 
[2, 3, 1], [3, 3, 1], [1, 1, 2], [2, 1, 2], [3, 1, 2], [1, 2, 2], [2, 2, 2], 
[3, 2, 2], [1, 3, 2], [2, 3, 2], [3, 3, 2], [1, 1, 3], [2, 1, 3], [3, 1, 3], 
[1, 2, 3], [2, 2, 3], [3, 2, 3], [1, 3, 3], [2, 3, 3], [3, 3, 3]] 
0

我認爲你在尋找什麼叫做一組的cartesian power

我不確定你爲什麼不能使用itertools,但我認爲應該指出一個安全措施的例子,即使你不使用它。

>>> import itertools 
>>> set1 = {'a', 'b'} 
>>> list(itertools.product(set1, repeat=0)) 
[()] 
>>> list(itertools.product(set1, repeat=1)) 
[('a',), ('b',)] 
>>> list(itertools.product(set1, repeat=2)) 
[('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b')] 

遞歸當你需要模仿n個嵌套for循環時派上用場。

def cartesian_power(seq, p): 
    if p == 0: 
     return [()] 
    else: 
     result = [] 
     for x1 in seq: 
      for x2 in cartesian_power(seq, p - 1): 
       result.append((x1,) + x2) 
     return result 

>>> cartesian_power([1, 2], 0) 
[()] 
>>> cartesian_power([1, 2], 1) 
[(1,), (2,)] 
>>> cartesian_power([1, 2], 2) 
[(1, 1), (1, 2), (2, 1), (2, 2)] 
>>>