2010-01-30 37 views
5

Bir liste L = var [a, b, c] ve ben küpe bir listesini oluşturmak istiyorum: Ben L * L yapıyor denedim ama işe yaramadıListe çarpma

[(a,a), (a,b), (a,c), (b,a), (b,b), (b,c)...] 

. Birisi bunu python'da nasıl elde edeceğimi söyler.

+0

Bu tür "ürün", "Kartezyen ürün" veya "doğrudan ürün" olarak da adlandırılır (burada bir terim veya diğerinin daha uygun olduğundan emin değilim, ancak Python belgesinin kendisi "Kartezyen ürün" kullanıyor) – MatrixFrog

cevap

13

itertools modül şey bu tür için yararlı fonksiyonları bir dizi içerir.

>>> import itertools 
>>> L = [1,2,3] 
>>> itertools.product(L,L) 
<itertools.product object at 0x83788> 
>>> list(_) 
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)] 
7

product üye sağlayan itertools modülüne bir göz atın.

L =[1,2,3] 

import itertools 
res = list(itertools.product(L,L)) 
print(res) 

verir:

[(1,1),(1,2),(1,3),(2,1), .... and so on] 
22

Bir liste anlayışı ile bunu yapabilirsiniz: Eğer product arıyor olabilir gibi görünüyor

[ (x,y) for x in L for y in L] 

düzenlemek

diğerleri gibi de itertools.product kullanabilirsiniz önerdi, ama sadece 2.6 kullanıyorsanız. Liste kavraması, Python'un 2.0'dan sonraki tüm sürümlerinde çalışacaktır. Eğer itertools.product'u kullanırsanız, bir liste yerine bir jeneratör döndürdüğünü aklınızda bulundurun. Bu yüzden onu dönüştürmeniz gerekebilir (bununla ne yapmak istediğinize bağlı olarak).

+0

Açıklama için teşekkürler. – Schitti

0

, x = [a, b, c] y = [] x madde için : x Item2 için : y.append ((et, item2))

Belki Pythonic yolu [L x L x (x, y)]

L2 = ve L kare var: ancak çalışma

0

Ok I çalıştı.

Bunu yapmanın en iyi pythonik yolu bu mu? L * L'nin python'da çalışmasını beklerdim.

+0

Hatalı beklentiler - 'sıra * sekansı ** ** değil ** tanımlandı (sadece' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''. –

+0

Oops, bunu cevapları görmeden önce yazdım. Lütfen – Schitti

3

iki ana alternatifleri:

>>> L = ['a', 'b', 'c'] 
>>> import itertools 
>>> list(itertools.product(L, L)) 
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')] 
>>> [(one, two) for one in L for two in L] 
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')] 
>>> 

eski bir Python 2.6 veya daha ihtiyacı var - bağlı olabilir neredeyse her Python sürümü ikincisi çalışır. Bu O bir çalışma zamanını sahiptir (n^2) ve bu nedenle oldukça yavaş

def perm(L): 
    result = [] 
    for i in L: 
     for j in L: 
      result.append((i,j)) 
    return result 

, ancak bunu "vintage" tarzı olması düşünebiliriz:

+0

'u dikkate almayın. Istertools'u kullanmak, sadece bir listeye doğrudan dönecek olursanız bana tuhaf geliyor.Liste kavraması muhtemelen daha etkilidir, tıpkı okunabilir ve muhtemelen daha fazla sürdürülebilir olduğu için, doğrudan ifadeye yapabileceğiniz ince ayarlamalar vardır. Daha fazla soyutlama daha fazla bükülmezlik anlamına gelebilir ve bütün mesele, sizin umursamayacağınız ayrıntıları (* umar *) (ama emin olamayacağınız) saklamaktır. – Steve314

0

yapmanın en eski moda yolu olurdu kodu.

+0

Bunun için tüm yaklaşımlar en iyi O (n^2) çalışma süresine sahiptir, bu nedenle hepsinin O (n^2) tuplesini oluşturmaları gerekir. Itertools gibi bir yineleyici kullanmak, bu çalışmanın bir kısmını ertelemenize izin verir, ancak tamamen bundan kaçınamazsınız. Yaklaşımınız O (n^3) bile olabilir - kesin hatırlamama rağmen, listelere eklenmek, bellek yeniden tahsis sorunları nedeniyle O (1) yerine O (n) olabilir. Ben * düşünüyorum * Python listesi yeniden boyutlandırılabilir bir dizi - * değil * bağlantılı bir liste kullanır. Yine de bir çeşit optimizasyon olabilir. Liste kavraması * muhtemelen * tüm diziyi başlangıçta önceden ayırır. – Steve314