リスト内の要素のすべてのペアに対する操作


94

Pythonを使用して、リスト内のすべての可能なペアを比較したいと思います。

私が持っていると仮定します

my_list = [1,2,3,4]

リストの2つの要素のすべての組み合わせに対して操作(fooとしましょう)を実行したいと思います。

最終結果は次のようになるはずです

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

私が最初に考えたのは、リストを手動で2回繰り返すことでしたが、それは非常にPython的ではないようです。

回答:


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)

編集: 2つの非常に類似した関数も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
 .    .    .    .

これら3つの関数はすべてPython 2.6で導入されました。


1
奇妙なことに、私がitertools.product(my_list、2)を実行すると、intが呼び出し可能ではないというメッセージが表示されます。itertools.product(my_listという、繰り返し= 2):私はそれを変更すると作品
ojrac

itertools.product()はPython 2.6の新機能であることに注意してください。
Mike Mazur、

後世のために、元の例ではitertools.combinationsがfoo(1,1)またはfoo(4,4)行を生成しないことを指摘しておきます。
カイロタン2009年

2
また、combinations_with_replacement()もあります。Combinations()に似ていますが、(イラストに合わせて)対角線を含みます。
Ziegl 2018年

1
怠け者の場合:と上記の結果を得るために、permutations()およびcombinations()使用r=2の代わりにrepeat=2するための一例で使用されるproduct()
ロブ・

15

私は同様の問題があり、ここで解決策を見つけました。モジュールをインポートしなくても機能します。

次のようなリストを想定します。

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

簡略化された1行のソリューションは次のようになります。

重複を含むすべての可能なペア

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 2017年

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 2019年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.