2016-09-17 49 views
3

爲了簡單起見,我在列表中提供了2個列表,但實際上我處理了列表中的數百個列表,每個列表包含大量的字典。我只想在第一個字典中獲取'status'鍵的值,而不檢查該列表中的任何其他字典(因爲我知道它們在該鍵中都包含相同的值)。然後我會在每個大詞典中執行某種聚類。我需要有效地連接所有'標題'值。有沒有辦法讓我的代碼更優雅,更快?更快,更'pythonic'字典列表

我:

nested = [ 
    [ 
     {'id': 287, 'title': 'hungry badger', 'status': 'High'}, 
     {'id': 437, 'title': 'roadtrip to Kansas','status': 'High'} 
    ], 
    [ 
     {'id': 456, 'title': 'happy title here','status': 'Medium'}, 
     {'id': 342,'title': 'soft big bear','status': 'Medium'} 
    ] 
] 

我想:

result = [ 
    { 
     'High': [ 
      {'id': 287, 'title': 'hungry badger'}, 
      {'id': 437, 'title': 'roadtrip to Kansas'} 
     ] 
    }, 
    { 
     'Medium': [ 
      {'id': 456, 'title': 'happy title here'}, 
      {'id': 342, 'title': 'soft big bear'} 
     ] 
    } 
] 

我試了一下:

for oneList in nested: 
    result= {} 
    for i in oneList:   
     a= list(i.keys()) 
     m= [i[key] for key in a if key not in ['id','title']] 
     result[m[0]]=oneList 
     for key in a: 
      if key not in ['id','title']: 
       del i[key] 

回答

2
from itertools import groupby  
result = groupby(sum(nested,[]), lambda x: x['status']) 

工作原理:

sum(nested,[])會連接所有外部列表連成的一個詞典大名單

groupby(, lambda x: x['status'])組所有對象通過他們的狀態屬性

注意,所以如果你想itertools.groupby返回一個生成器(不是列表),物化發電機,你需要做如下的事情。

from itertools import groupby  
result = groupby(sum(nested,[]), lambda x: x['status']) 
result = {key:list(val) for key,val in result} 
+0

OMG! @。@ 哇。你的解決方案如此之快。非常感謝你!!!!完美的作品。 – el347

+1

一:不要使用sum(nested,[])'。這是平緩的最慢的方法,並且越平緩越慢(它創建'n'臨時'列表',每次越來越多)。你已經在使用'itertools'了,你正在迭代結果(根本不需要一個真正的'list'),所以只需使用'itertools.chain.from_iterable'來平坦化(因爲'lambda'是邪惡的/ slow時不需要,''operator.itemgetter'爲'key'):'groupby(chain.from_iterable(嵌套),itemgetter('status'))'。 ['sum(x,[])'是_slow_(見註釋)](http://stackoverflow.com/a/39520827/364696)。 – ShadowRanger

+1

@ShadowRanger謝謝你!剛剛運行這個:從itertools導入鏈; 進口經營者; s = groupby(chain.from_iterable(results),key = operator.itemgetter('status')); for key,grp in s:print(key,list(grp))一切都很好。 – el347

2

你可以爲每個嵌套列表defaultdict

import collections 
nested = [ 
[{'id': 287, 'title': 'hungry badger', 'status': 'High'}, 
{'id': 437, 'title': 'roadtrip to Kansas','status': 'High'}],  
[{'id': 456, 'title': 'happy title here','status': 'Medium'}, 
{'id': 342,'title': 'soft big bear','status': 'Medium'}] ] 
result = [] 
for l in nested: 
    r = collections.defaultdict(list) 
    for d in l: 
     name = d.pop('status') 
     r[name].append(d) 
    result.append(r) 

這給出了以下result

>>> import pprint 
>>> pprint.pprint(result) 
[{'High': [{'id': 287, 'title': 'hungry badger'}, 
      {'id': 437, 'title': 'roadtrip to Kansas'}]}, 
{'Medium': [{'id': 456, 'title': 'happy title here'}, 
      {'id': 342, 'title': 'soft big bear'}]}] 
+0

太棒了。 TNX!每天在這裏學習新的東西。呵呵。 itertools的groupby解決方案看起來非常好;降低複雜性。你的回答教會了我關於collections.defaultdict()。再次感謝。 – el347

+0

哦,真好! Ur解決方案消除了狀態,並做我在問什麼。我會把這兩個時間都用於這些,並且還會用itertools的groupby來玩更多...感謝幫助,man! – el347