2016-05-12 14 views
0

ミントシナモン17.3のPython 2.7。 私はdictsのリストを採用しているテストコードを少し持っていますが、何時間もの欲求不満にもかかわらず、なぜそれがうまくいかないのか分かりません。dictsのリストを参照

blockagedict = {'location': None, 'timestamp': None, 'blocked': None} 
blockedlist = [blockagedict] 

blockagedict['location'] = 'A' 
blockagedict['timestamp'] = '12-Apr-2016 01:01:08.702149' 
blockagedict['blocked'] = True 

blockagedict['location'] = 'B' 
blockagedict['timestamp'] = '12-Apr-2016 01:01:09.312459' 
blockagedict['blocked'] = False 
blockedlist.append(blockagedict) 

for test in blockedlist: 
    print test['location'], test['timestamp'], test['blocked'] 

これは、常に次の出力を生成し、私はなぜうまくいかないことができると私は自分のコードに何かを持っているかどうかを確認することはできません。これは、常にdict値の最後のセットを出力しますが、私が間違っていなければ、すべてを出力しなければなりません。

B 12-Apr-2016 01:01:09.312459 False 
B 12-Apr-2016 01:01:09.312459 False 

誰かが自分のやり方の誤りを見せて、私を悲惨さから救うことができれば嬉しいです。

答えて

1

パフォーマンスに関心があり、リストに100万の辞書があり、すべて同じキーであれば、NumPy構造化配列を使用する方がよいでしょう。基本的に行の行列であり、適切な型の名前付き列である単一の効率的なデータ構造を持つことができます。あなたはコメントで、行の数を事前に知っているかもしれないと言いました。代わりにNumPyを使用しているサンプルコードを書き直してみましょう。これは百万語のリストよりも大幅に効率的です。

import numpy as np 

dtype = [('location', str, 1), ('timestamp', str, 27), ('blocked', bool)] 

count = 2 # will be much larger in the real program 

blockages = np.empty(count, dtype) # use zeros() instead if some data may never be populated 

blockages[0]['location'] = 'A' 
blockages[0]['timestamp'] = '12-Apr-2016 01:01:08.702149' 
blockages[0]['blocked'] = True 

blockages['location'][1] = 'B' # n.b. indexing works this way too 
blockages['timestamp'][1] = '12-Apr-2016 01:01:09.312459' 
blockages['blocked'][1] = False 

for test in blockages: 
    print test['location'], test['timestamp'], test['blocked'] 

使用方法はほぼ同じです。しかし、ストレージは固定サイズで、単一の割り当てになっています。これにより、メモリ使用量と計算時間が短縮されます。

良い副作用として、上記のように記述すると、元々の問題が完全に回避され、同じ行への複数の参照が完全に回避されます。これで、すべてのデータが、オブジェクト参照のない行列に直接配置されます。


コメントが残っていますが、NumPyはインストールされていない可能性があるため、使用できません。私は(この方法は、それぞれの値が正確に1バイトを取る)固定サイズblocked値の効率的な保管のためにここにarrayを使用

from array import array 

blockages = {'location': [], 'timestamp': [], 'blocked': array('B')} 

blockages['location'].append('A') 
blockages['timestamp'].append('12-Apr-2016 01:01:08.702149') 
blockages['blocked'].append(True) 

blockages['location'].append('B') 
blockages['timestamp'].append('12-Apr-2016 01:01:09.312459') 
blockages['blocked'].append(False) 

for location, timestamp, blocked in zip(*blockages.values()): 
    print location, timestamp, blocked 

注:まあ、我々はまだこのような不要なdictsを、避けることができます。

あなたは避けることのできるリサイズ可能なリストで終わりますが、少なくともリストのすべてのスロットにdictを保存する必要はありません。これはもっと効率的であるはずです。

+0

私は実際にnumpyを使用することは考えていませんでしたが、以前はそれを使用したことはありませんでした。今までのところ:-) –

+0

実際には、考えて、numpyを使用することはできませんマシンにインストールされるものの制御。 –

+1

@ DaveJ1961:適度に効率的な非NumPyソリューションも追加しました。 –

4

行番号blockedlist = [blockagedict]は、実際にはコピーではなく、dictへの参照をリストに格納しているためです。あなたのコードは、まったく同じオブジェクトに対する2つの参照を持つリストを効果的に作成します。

+0

どうすればいいですか? –

+0

あなたは誰がオブジェクトを所有しているか考える必要があります。 IMOは、すべてのリスト要素に対して新しいdictオブジェクトを作成して(リストに完全に渡す)、既存のものを再割り当てするのではなく、クリーンな方法です。 –

+0

リストのサイズを知っていたら、appendを使う代わりにリスト全体を初期化できないのでしょうか?リストには、1〜200万アイテムのオーダーがあります。 –

0

私はバットのすぐ下のディクテーションのリストを初期化しました。これはうまくいくようです。私はこのためのクラスを書くように誘惑されますが。

blockedlist = [{'location': None, 'timestamp': None, 'blocked': None} for k in range(2)] 

blockedlist[0]['location'] = 'A' 
blockedlist[0]['timestamp'] = '12-Apr-2016 01:01:08.702149' 
blockedlist[0]['blocked'] = True 

blockedlist[1]['location'] = 'B' 
blockedlist[1]['timestamp'] = '12-Apr-2016 01:01:09.312459' 
blockedlist[1]['blocked'] = False 

for test in blockedlist: 
    print test['location'], test['timestamp'], test['blocked'] 

そして、これは私が探していたものを生成します。私は100万〜2行で、テキストファイルからの読み取り、その行を反復処理するコードに変換されます

A 12-Apr-2016 01:01:08.702149 True 
B 12-Apr-2016 01:01:09.312459 False 

ません。問題である。

関連する問題