2017-02-14 9 views
3

辞書形式で格納された要素のリストがあります。辞書項目のリストの最小要素と最大要素の検索

input_list = [ {'item1': 2, 'item2': 4, 'item3': 3, 'item4': 5, 'item5': 1, 'item6': 2, 'item7': 2, 'item8': 1, 'item9': 2, 'item10': 5, 'item11': 1, 'item12': 2}, 
    {'item1': 4, 'item2': 1, 'item3': 6, 'item4': 2, 'item5': 11, 'item6': 3, 'item7': 4, 'item8': 6, 'item9': 1, 'item10': 5, 'item11': 1, 'item12': 3}] 

私はinput_listで約150の要素を持っていると私はアイテムを辞書などの要素を持っていなければならない二つの出力リスト(output_list_maxとoutput_list_min)を作成する必要があります(つまりITEM1、item2..etc)キーなどと各項目の最大値/最小値(input_list内の項目へのwrt)を値として返します。

For.eg

output_list_max = [{'item1': 4, 'item2': 4, 'item3': 6, 'item4': 5, 'item5': 11, 'item6': 3, 'item7': 4, 'item8': 6, 'item9': 2, 'item10': 5, 'item11': 1, 'item12': 3}] 

output_list_min = [{'item1': 2, 'item2': 1, 'item3': 3, 'item4': 2, 'item5': 1, 'item6': 2, 'item7': 2, 'item8': 1, 'item9': 1, 'item10': 5, 'item11': 1, 'item12': 2}] 

私は、リストや辞書を反復処理することによってこれを行うことができますが、私はリストとしてそうする最も効率的かつ神託の方法を知りたいと辞書が1000年まで可能。

私は私の意図をクリアすることができました願っています:)

すべてのヘルプは感謝を理解されるであろう!

+0

ですから、*要素ごとの*最小値と最大値をしたいですか? –

+0

辞書の1つにキーがない場合はどうなりますか? '[{'a':1、 'b':2}、{'a':3}]'のように? –

+0

はい、正確です。要素別の最大値と最小値 – blackbug

答えて

2

あなたはfunctools.reduceを使用してCounterを使用し、それらの上に&(要素ごとの最小値)と|(要素単位の最大)を使用することができます

from functools import reduce 
from collections import Counter 

output_list_max = dict(reduce(lambda x,y:x|y,map(Counter,input_list))) 
output_list_min = dict(reduce(lambda x,y:x&y,map(Counter,input_list))) 

をREPLで:

>>> output_list_max 
{'item4': 5, 'item10': 5, 'item3': 6, 'item9': 2, 'item8': 6, 'item2': 4, 'item12': 3, 'item7': 4, 'item6': 3, 'item11': 1, 'item1': 4, 'item5': 11} 
>>> output_list_min 
{'item4': 2, 'item10': 5, 'item3': 3, 'item9': 1, 'item8': 1, 'item2': 1, 'item12': 2, 'item7': 2, 'item6': 2, 'item11': 1, 'item1': 2, 'item5': 1} 

結果は辞書であり、ではなくのリストが1つの辞書を含んでいますが、結果をリストに入れることはむしろ役に立たないことに注意してください。

これは、最初にmapを使用して、辞書のリストをCounterのリストに変換するためです。これはmap(Counter,input_list)を使用して行われます。

次に、reduce(..)が使用されます(一部の機能言語では、これはfoldと呼ばれます)。 reduce(..)の要素のリスト[x1,x2,...,xn]fと入力すると、f(...f(f(x1,x2),x3)...,xn)が返されます。この場合、このように計算されます(最初の要素x1|x2|x3|...|xn)。 |は要素ごとの最大値であるため、アキュムレータ(これまでの最大値を保持するカウンタ)があり、新しい辞書ごとに新しい最大値が計算されます。この結果はreduceによって返されます。

+0

私は間違っていると思われますが、これは、すべてのディクテーションに対して繰り返し実行するよりも約5倍遅く実行されました。 (たぶん私はより多くのdictsを追加する必要がありますか?) – glibdud

+0

あなたは素晴らしいです! :)それは完璧に動作します!ありがとう!可能であれば、どのように動作するかを説明することができます。 – blackbug

+0

@glibdud:辞書を反復するとどういう意味ですか?あなたが計算を行っているので、単純に反復して何もしないよりも遅くなります。 –

4

あなたの辞書項目をペアリングするsorted()zip()を使用することができます。

lst = list(zip(*[sorted(d.items()) for d in input_list])) 

dict(max(item) for item in lst) 
# {'item9': 2, 'item4': 5, 'item5': 11, 'item11': 1, 'item2': 4, 'item1': 4, 'item10': 5, 'item6': 3, 'item3': 6, 'item12': 3, 'item7': 4, 'item8': 6} 

dict(min(item) for item in lst) 
# {'item9': 1, 'item4': 2, 'item5': 1, 'item11': 1, 'item2': 1, 'item1': 2, 'item10': 5, 'item6': 2, 'item3': 3, 'item12': 2, 'item7': 2, 'item8': 1} 
+3

+1ウィレムは面白くて賢いですが、これは理解しやすく、素早い 'timeit'テストでは数倍速く見えます。 – glibdud

関連する問題