2009-06-03 31 views
50

Python'u kullanarak, olası tüm eşleri bir listede karşılaştırmak isterim.Bir listedeki her öğe çiftinin üzerinde işlem yapılması

Ben Bir ameliyat yapmak istiyorum

my_list = [1,2,3,4] 

varsayalım listeden 2 elemanların her kombinasyonuna (haydi foo diyebiliriz).

nihai sonuç ilk düşüncem elle Listede iki kez yineleme oldu

foo(1,1) 
foo(1,2) 
... 
foo(4,3) 
foo(4,4) 

aynı olmalıdır, ama bu çok pythonic görünmüyor.

cevap

141

itertools modülünde product()'a bakın. Açıkladığınız şeyi yapar.

my_list = [1,2,3,4] 
for x in my_list: 
    for y in my_list: 
     foo(x, y) 

Düzenleme:

import itertools 

my_list = [1,2,3,4] 
for pair in itertools.product(my_list, repeat=2): 
    foo(*pair) 

Bu eşdeğerdir iki çok benzer işlevler de vardır, permutations() ve combinations(). onlar nasıl farklı göstermek için:

. 1,2 1,3 1,4 
2,1 . 2,3 2,4 
3,1 3,2 . 3,4 
4,1 4,2 4,3 . 
:

1,1 1,2 1,3 1,4 
2,1 2,2 2,3 2,4 
3,1 3,2 3,3 3,4 
4,1 4,2 4,3 4,4 

permutations()x,x çiftleri ortadan kaldırarak, elemanların her benzersiz çiftinin tüm benzersiz orderings oluşturur:

product() tüm kopyaların dahil unsurların mümkün olan her türlü eşleştirme, üretir

Son olarak, combinations(), her bir benzersiz öğe çiftini yalnızca sözcüksel düzende oluşturur:

Bu işlevlerin üçü Python 2.6'da tanıtıldı. Eğer işlev çağrısının sonuçlarına listesini toplamak istiyorsanız

for i in my_list: 
    for j in my_list: 
     foo(i, j) 

, yapabileceğiniz: sadece bir fonksiyonu arıyorsan

+1

Itertools'u bilmiyordum, bu mükemmel. Teşekkürler ! – GuiSim

+1

Tek, itertools.product (my_list, 2) çalıştırdığımda, int'nin callable olmadığından şikayet ediyor. Bunu değiştirdikten sonra çalışır: itertools.product (my_list, yineleme = 2) – ojrac

+0

(Python 2.6.2 kullanarak) – ojrac

2

, gerçekten çok daha iyi yapamaz

size her olası çiftinin (i, j) için foo(i, j) uygulanması sonucu bir listesini döndürür
[foo(i, j) for i my_list for j in my_list] 

.

5

Benzer bir sorunla karşılaştım ve here numaralı özümü buldu. Herhangi bir modülü almak zorunda kalmadan çalışır.

people = ["Lisa","Pam","Phil","John"] 

Basitleştirilmiş tek satırlık çözüm şu şekilde görünecektir:

gibi bir liste varsayalım.

Tüm olası çiftleri dahil çiftleri:

result = [foo(p1, p2) for p1 in people for p2 in people] 

Tüm olası çiftleri hariç çiftleri:

result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2] 

Eşsiz çiftleri, sıralamasının bir önemi yoktur:

result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))] 

Çalışmak istemiyorsanız, sadece çiftleri almak için foo işlevini kaldırarak ve yalnızca bir tuple kullanmak yeterli olacaktır.

Tüm olası çiftleri dahil çiftleri:

list_of_pairs = [(p1, p2) for p1 in people for p2 in people] 

Sonuç:

('Lisa', 'Lisa') 
('Lisa', 'Pam') 
('Lisa', 'Phil') 
('Lisa', 'John') 
('Pam', 'Lisa') 
('Pam', 'Pam') 
('Pam', 'Phil') 
('Pam', 'John') 
('Phil', 'Lisa') 
('Phil', 'Pam') 
('Phil', 'Phil') 
('Phil', 'John') 
('John', 'Lisa') 
('John', 'Pam') 
('John', 'Phil') 
('John', 'John') 

Tüm olası çiftleri hariç çiftleri:

list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2] 

Sonuç:

('Lisa', 'Pam') 
('Lisa', 'Phil') 
('Lisa', 'John') 
('Pam', 'Lisa') 
('Pam', 'Phil') 
('Pam', 'John') 
('Phil', 'Lisa') 
('Phil', 'Pam') 
('Phil', 'John') 
('John', 'Lisa') 
('John', 'Pam') 
('John', 'Phil') 

Benzersiz çiftleri sıralamasının bir önemi yoktur:

list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))] 

Sonuç:

('Lisa', 'Pam') 
('Lisa', 'Phil') 
('Lisa', 'John') 
('Pam', 'Phil') 
('Pam', 'John') 
('Phil', 'John') 

Düzenleme: rework bu çözümü basitleştirmek için sonra, bunun aynı olduğunu fark Adam Rosenfield'den yaklaşım. Umarım daha büyük bir açıklama, bazılarının bunu daha iyi anlamasına yardımcı olur.

+1

Bunu çok daha temiz bir kütüphane almak için çok tercih ediyorum! –

İlgili konular