1. ホーム
  2. python

[解決済み] リストの各項目と残りの項目を一度だけ比較するには?

2023-03-23 17:14:51

質問

比較したいものの配列やリストがあるとします。私がより精通している言語では、私は次のようなことを行うでしょう。

for (int i = 0, i < mylist.size(); i++)
    for (int j = i + 1, j < mylist.size(); j++)
        compare(mylist[i], mylist[j])

これは、各ペアを一度だけ比較することを保証します。いくつかのコンテキストのために、私はリストに含まれるオブジェクトの束で衝突検出を行っています。検出された各衝突について、衝突を記述する小さな「衝突」オブジェクトがリストに追加され、別のルーチンがループして各衝突を解決します (衝突する 2 つのオブジェクトの性質に依存します)。明らかに、私は各衝突を一度だけ報告したいのです。

さて、Pythonはインデックスをループするよりもイテレータを使うことを好むので、これを行うためのPythonicな方法は何でしょうか?

私は以下のような(バグだらけの)コードを持っていました。

for this in mylist:
    for that in mylist:
        compare(this, that)

しかし、これは明らかに各衝突を2回ピックアップしており、それらを解決しようとすると奇妙な動作につながります。では、Pythonicな解決策は何でしょうか?

どのように解決するのでしょうか?

もちろん、これは各ペアを2回生成し、それぞれの for ループはリストのすべての項目を通過します。

を使うことができます。 itertools の魔法を使って、すべての可能な組み合わせを生成することができます。

import itertools
for a, b in itertools.combinations(mylist, 2):
    compare(a, b)

itertools.combinations は、各要素を反復可能な他の各要素と対にしますが、一度だけです。


インデックスベースのアイテムアクセスを使ってこれを書くことも可能で、あなたが慣れ親しんでいるものと同じように、ネストされた for ループを使用します。

for i in range(len(mylist)):
    for j in range(i + 1, len(mylist)):
        compare(mylist[i], mylist[j])

もちろん、この方法は見た目が悪く、パイソン的ではありませんが、時にはこれが最も簡単で理解しやすい解決方法であることもありますから、このような問題を解決することを敬遠すべきではありません。