Operacja na każdej parze elementów na liście


101

Używając Pythona, chciałbym porównać każdą możliwą parę na liście.

Przypuśćmy, że tak

my_list = [1,2,3,4]

Chciałbym wykonać operację (nazwijmy to foo) na każdej kombinacji 2 elementów z listy.

Ostateczny wynik powinien być taki sam jak

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

Moją pierwszą myślą było ręczne powtórzenie listy dwukrotnie, ale nie wydaje się to zbyt pytoniczne.

Odpowiedzi:


240

Sprawdź product()w itertoolsmodule. Robi dokładnie to, co opisujesz.

import itertools

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

Jest to równoważne z:

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

Edycja: Istnieją również dwie bardzo podobne funkcje permutations()i combinations(). Aby zilustrować, czym się różnią:

product() generuje wszystkie możliwe pary elementów, w tym wszystkie duplikaty:

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()generuje wszystkie unikalne uporządkowania każdej unikalnej pary elementów, eliminując x,xduplikaty:

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

Wreszcie combinations()generuje tylko każdą unikalną parę elementów w porządku leksykograficznym:

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

Wszystkie trzy funkcje zostały wprowadzone w Pythonie 2.6.


1
Dziwne, kiedy uruchamiam itertools.product (my_list, 2), narzeka, że ​​int nie jest wywoływalny. Działa po zmianie na: itertools.product (my_list, repeat = 2)
ojrac

Zauważ, że itertools.product () jest nowością w Pythonie 2.6.
Mike Mazur

Dla potomności wskażę, że itertools.combinations nie wygenerowałoby linii foo (1,1) ani foo (4,4) w oryginalnym przykładzie.
Kylotan

3
Istnieje również complex_with_replacement (). Jak kombinacje (), ale z uwzględnieniem przekątnej (zgodnie z ilustracjami).
Ziegl

1
Dla leniwych: Aby uzyskać powyższe wyniki permutations()i combinations()użyć r=2zamiast ich repeat=2użycia w przykładzie dlaproduct()
Rob

16

Miałem podobny problem i znaleźć rozwiązanie tutaj . Działa bez konieczności importowania żadnego modułu.

Przypuśćmy, że lista taka jak:

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

Tak wyglądałoby uproszczone rozwiązanie jednowierszowe.

Wszystkie możliwe pary , w tym duplikaty:

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

Wszystkie możliwe pary, z wyłączeniem duplikatów :

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

Unikalne pary , w których kolejność nie ma znaczenia:

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

Jeśli nie chcesz operować, ale po prostu uzyskać pary, foowystarczy usunąć funkcję i użyć tylko krotki.

Wszystkie możliwe pary , w tym duplikaty:

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

Wynik:

('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')

Wszystkie możliwe pary, z wyłączeniem duplikatów :

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

Wynik:

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

Unikalne pary , w których kolejność nie ma znaczenia:

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

Wynik:

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

Edycja: Po przeróbce mającej na celu uproszczenie tego rozwiązania zdałem sobie sprawę, że jest to to samo podejście, co Adam Rosenfield. Mam nadzieję, że szersze wyjaśnienie pomoże niektórym lepiej to zrozumieć.


2
Zdecydowanie wolę to od importowania biblioteki, znacznie czystszej!
sudo-nim

1
itertools jest częścią Pythona. To nie jest biblioteka zewnętrzna.
GuiSim,

3

Jeśli po prostu wywołujesz funkcję, nie możesz zrobić nic lepszego niż:

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

Jeśli chcesz zebrać listę wyników wywołania funkcji, możesz:

[foo(i, j) for i in my_list for j in my_list]

co zwróci listę wyników zastosowania foo(i, j)do każdej możliwej pary (i, j).


0
my_list = [1,2,3,4]

pairs=[[x,y] for x in my_list for y in my_list]
print (pairs)

Chociaż ten kod może rozwiązać problem, dobra odpowiedź wymaga również wyjaśnienia, co robi kod i jak rozwiązuje problem.
BDL,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.