0

defaultdictsのリストを初期化する必要があります。たとえば、文字列の場合、これは整然としています。

list_of_dds = [string] * n

…しかし、可変の場合、あなたはそのアプローチですぐに混乱します:

>>> x=[defaultdict(list)] * 3
>>> x[0]['foo'] = 'bar'
>>> x
[defaultdict(<type 'list'>, {'foo': 'bar'}), defaultdict(<type 'list'>, {'foo': 'bar'}), defaultdict(<type 'list'>, {'foo': 'bar'})]

欲しいのは、defaultdictsの新しく作成された個別のインスタンスの反復可能です。私がすることができます:

list_of_dds = [defaultdict(list) for i in xrange(n)]

しかし、ここでリスト内包表記を使用すると少し汚く感じます。もっと良いアプローチがあると思います。ある?それが何であるか教えてください。

編集:

これが、リスト内包表記が最適ではないと感じる理由です。私は通常、事前最適化タイプではありませんが、ここで速度の違いを無視することはできません。

>>> timeit('x=[string.letters]*100', setup='import string')
0.9318461418151855
>>> timeit('x=[string.letters for i in xrange(100)]', setup='import string')
12.606678009033203
>>> timeit('x=[[]]*100')
0.890861988067627
>>> timeit('x=[[] for i in xrange(100)]')
9.716886043548584
4

2 に答える 2

2

リスト内包表記を使用したアプローチは正しいです。どうして汚れていると思いますか?必要なのは、長さがいくつかの基本セットによって定義されているもののリストです。リスト内包表記は、いくつかの基本セットに基づいてリストを作成します。ここでリスト内包表記を使用することの何が問題になっていますか?

編集:速度の違いは、あなたがやろうとしていることの直接的な結果です。 [[]]*100リストを1つ作成するだけでよいため、より高速です。毎回新しいリストを作成するのは遅くなりますが、実際に100の異なるリストが必要な場合は、遅くなることを期待する必要があります。

(文字列の例で毎回新しい文字列を作成するわけではありませんが、リスト内包表記はすべての要素が同じになることを事前に「知る」ことができないため、それでも遅くなります。毎回式を再評価します。リスト内包の内部の詳細はわかりませんが、最初から反復可能なインデックスのサイズが必ずしもわからないため、リストのサイズ変更のオーバーヘッドが発生する可能性もあります。 tリストを事前に割り当てます。さらに、文字列の例の速度低下の一部は、string.lettersすべての反復でルックアップすることによるものであることに注意してください。timeit.timeit('x=[letters for i in xrange(100)]', setup='from string import letters')代わりに---string.letters一度だけルックアップする---を使用する私のシステムでは、時間が約30%短縮されます。 )。

于 2012-07-25T21:42:21.780 に答える
1

リスト内包表記はまさにあなたが使うべきものです。

リストの乗算の問題は、単一の可変オブジェクトを含むリストが作成され、それを複製しようとすることです。ただし、オブジェクト自体からオブジェクトを複製しようとすると、オブジェクトの作成に使用されたコードは関連しなくなります。オブジェクトは、オブジェクトの作成に使用されたコードを認識していないため、オブジェクトの作成に使用されたコードをN回実行することで、オブジェクトを操作することはできませ

copy.copyまたはcopy.deepcopyを使用して複製することもできますが、copy / deepcopyの呼び出しが、N回実行する必要のあるコードになるため、同じボートに戻ることができます。

リスト内包表記は、ここに非常に適しています。どうしたの?

于 2012-07-25T21:59:29.843 に答える