목록의 모든 요소 쌍에 대한 작업


94

Python을 사용하여 목록에서 가능한 모든 쌍을 비교하고 싶습니다.

내가 가지고 있다고 가정

my_list = [1,2,3,4]

목록에서 두 요소의 모든 조합에 대해 작업을 수행하고 싶습니다 (foo라고 부르겠습니다).

최종 결과는 다음과 같아야합니다.

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

내 첫 번째 생각은 목록을 수동으로 두 번 반복하는 것이었지만 그다지 비단 해 보이지는 않습니다.

답변:


229

모듈 product()에서 확인하십시오 itertools. 그것은 당신이 설명하는 것과 정확히 일치합니다.

import itertools

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

이것은 다음과 동일합니다.

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

편집 : 이 아니라 두 개의 매우 유사한 기능이 있고, permutations()하고 combinations(). 차이점을 설명하려면 :

product() 모든 중복을 포함하여 가능한 모든 요소 쌍을 생성합니다.

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중복을 제거합니다 .

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

마지막으로 combinations()사전 순으로 고유 한 각 요소 쌍만 생성합니다.

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

이 세 가지 함수는 모두 Python 2.6에서 도입되었습니다.


1
이상하게도 itertools.product (my_list, 2) 실행하면 int를 호출 할 수 없다고 불평합니다. 내가 그것을 변경하면 작동합니다 : itertools.product (my_list, repeat = 2)
ojrac

itertools.product ()는 Python 2.6의 새로운 기능입니다.
Mike Mazur

후손을 위해 itertools.combinations는 원래 예제에서 foo (1,1) 또는 foo (4,4) 행을 생성하지 않는다는 점을 지적합니다.
Kylotan

2
또한 combination_with_replacement ()가 있습니다. combination ()과 비슷하지만 대각선을 포함합니다 (그림과 동일).
Ziegl

1
위의와 결과 활용하려면 다음 게으른 들어 permutations()combinations()사용 r=2대신에 repeat=2대한 예제를 사용product()

15

비슷한 문제가 있었고 여기 에서 해결책을 찾았습니다 . 모듈을 가져올 필요없이 작동합니다.

다음과 같은 목록을 가정합니다.

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

단순화 된 단선 솔루션은 다음과 같습니다.

중복을 포함하여 가능한 모든 쌍 :

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

중복을 제외한 모든 가능한 쌍 :

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

순서가 무관 한 고유 쌍 :

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

작동하지 않고 쌍을 얻기 위해 함수를 제거하고 foo튜플 만 사용하면 충분합니다.

중복을 포함하여 가능한 모든 쌍 :

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

결과:

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

중복을 제외한 모든 가능한 쌍 :

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

결과:

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

순서가 무관 한 고유 쌍 :

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

결과:

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

편집 :이 솔루션을 단순화하기 위해 재 작업 한 후 Adam Rosenfield와 동일한 접근 방식임을 깨달았습니다. 더 큰 설명이 일부 사람들이 더 잘 이해하는 데 도움이되기를 바랍니다.


2
나는 라이브러리를 가져 오는 것보다 이것을 훨씬 더 깨끗하게 선호합니다!
sudo-nim

itertools는 Python의 일부입니다. 외부 라이브러리가 아닙니다.
GuiSim

2

함수를 호출하는 경우 다음보다 훨씬 더 잘할 수 없습니다.

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

함수 호출 결과 목록을 수집하려면 다음을 수행 할 수 있습니다.

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

그러면 foo(i, j)가능한 각 쌍 에 적용한 결과 목록이 반환됩니다 (i, j).


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

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

이 코드는 문제를 해결할 수 있지만, 좋은 답변도에 대한 설명이 필요 어떤 코드가 수행을하고 어떻게 그 문제를 해결한다.
BDL
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.