次のようなリスト内包表記があります。
cart = [ ((p,pp),(q,qq)) for ((p,pp),(q,qq))\
in itertools.product(C.items(), repeat=2)\
if p[1:] == q[:-1] ]
C
任意の整数のタプルであるキーを持つ dict です。すべてのタプルは同じ長さです。最悪の場合、すべての組み合わせを新しいリストに含める必要があります。これは非常に頻繁に発生する可能性があります。
例として、次のような辞書があります。
C = { (0,1):'b',
(2,0):'c',
(0,0):'d' }
そして、結果を次のようにしたい:
cart = [ (((2, 0), 'c'), ((0, 1), 'b'))
(((2, 0), 'c'), ((0, 0), 'd'))
(((0, 0), 'd'), ((0, 1), 'b'))
(((0, 0), 'd'), ((0, 0), 'd')) ]
したがって、オーバーラップとは、たとえば、タプル(1,2,3,4)
と(2,3,4,5)
がオーバーラップ セクション (2,3,4) を持つことを指しています。オーバーラップするセクションは、タプルの「端」にある必要があります。タプルの長さよりも 1 短い長さのオーバーラップのみが必要です。したがって(1,2,3,4)
、 とは重複しません(3,4,5,6)
。また、タプルの最初または最後の要素を削除すると、最終的に不明確なタプルになる可能性があることに注意してください。これらすべてを他のすべての要素と比較する必要があります。この最後の点は、最初の例では強調されていません。
私のコード実行時間の大部分は、このリストの理解に費やされています。のすべての要素が常に必要なcart
ので、代わりにジェネレーターを使用してもスピードアップはないようです。
私の質問は次のとおりです。これを行うより速い方法はありますか?
私が考えていたのは、次のような 2 つの新しい辞書を作成しようとすることでした。
aa = defaultdict(list)
bb = defaultdict(list)
[aa[p[1:]].append(p) for p in C.keys()]
[bb[p[:-1]].append(p) for p in C.keys()]
そして、どういうわけか、リストの要素のすべての組み合わせをfor allaa[i]
のリストとマージしますが、このアイデアに頭を悩ませることもできません。bb[i]
i
アップデート
tobias_k と shx2 によって追加されたソリューションはどちらも、元のコードよりも複雑です (私が知る限り)。私のコードは O(n^2) ですが、他の 2 つのソリューションは O(n) です。ただし、私の問題のサイズと構成では、3 つのソリューションすべてが多かれ少なかれ同時に実行されているようです。これは、関数呼び出しに関連するオーバーヘッドと、使用しているデータの性質の組み合わせに関係していると思います。特に、キーの実際の構成だけでなく、異なるキーの数も大きな影響を与えているようです。後者は、完全にランダムなキーの場合、コードの実行がはるかに遅くなるためです。tobias_k の回答を受け入れたのは、彼のコードが最も理解しやすいためです。ただし、このタスクの実行方法に関する他の提案を大歓迎します。