2011-07-11 95 views
2

我有,我想重新組合成一個字典列表不同的字典,考慮到其不同的值:變換字典到詞典列表

字典:

[{'language': 'de', 'suggestion': 'fressen', 'comment': 'for animals'}, 
{'language': 'de', 'suggestion': 'essen', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'manger', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'bouffer', 'comment': 'slang'}] 

名單詞典:

[{'language': 'de', 'suggestion': ['fressen', 'essen'], 'comment': ['for animals', '']}, \ 
{'language': 'fr', 'suggestion': ['manger', 'bouffer'], 'comment': ['', 'slang'}] 

我還是一個初學者蟒蛇,我不知道從哪裏開始,把所有的字典用同樣的語言「:「德」的相同的字典。

+4

第一項數據結構(一個字典列表)是合理的:它類似於數據庫中的對象列表或行列表。你的第二個數據結構看起來很尷尬,因爲你最終會得到並行數組,其中'ith'建議必須與'ith'註釋保持同步。你是否考慮過一個口號的詞典,把語言作爲最高級別的關鍵詞('de','fr'等),把這個詞本身作爲二級關鍵詞(fressen,essen等)和評論作爲價值? – FMc

+0

事實上,我只想結束這類詞典,以便可以在模板中輕鬆使用它們,以便使用{{dictionary.language}}。如果密鑰是動態的,我實際上不知道如何渲染內容。 – Edouard

回答

4

一個簡單的解決方案,假設所有類型的字典的密鑰是相同的:

ld = [{'language': 'de', 'suggestion': 'fressen', 'comment': 'for animals'}, 
{'language': 'de', 'suggestion': 'essen', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'manger', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'bouffer', 'comment': 'slang'}] 

langs = {i['language'] for i in ld} 

d = [] 

for lang in langs: 
    d.append({"language": lang}) 
    for key in ld[0].keys() - ["language"]: 
     d[-1][key] = [i[key] for i in ld if i["language"] == lang] 

print(d) 

輸出:

[{'comment': ['', 'slang'], 
    'language': 'fr', 
    'suggestion': ['manger', 'bouffer']}, 
{'comment': ['for animals', ''], 
    'language': 'de', 
    'suggestion': ['fressen', 'essen']}] 

如果您選擇使用@上你的問題在他的評論中描述的FMC的數據結構,你可以使用那麼長的一行,用嵌套理解來做所有事情:

d = {lang: 
     {i["suggestion"]: i["comment"] 
     for i in ld if i["language"] == lang} 
    for lang in {i["language"] for i in ld}} 

print(d) 

輸出:

{'de': {'essen': '', 'fressen': 'for animals'}, 
'fr': {'bouffer': 'slang', 'manger': ''}} 
1

有點複雜的解決方案,但無論如何:

>>> dicts = [{'language': 'de', 'suggestion': 'fressen', 'comment': 'for animals'}, 
... {'language': 'de', 'suggestion': 'essen', 'comment': ''}, 
... {'language': 'fr', 'suggestion': 'manger', 'comment': ''}, 
... {'language': 'fr', 'suggestion': 'bouffer', 'comment': 'slang'}] 
>>> main_key = 'language' 
>>> result_dict = dict() 
>>> for d in dicts: 
...  for key, value in d.iteritems(): 
...    if key == main_key: 
...      result_dict.setdefault(d[main_key], dict())[main_key] = value 
...    else: 
...      result_dict.setdefault(d[main_key], dict()).setdefault(key, list()).append(value) 
... 
>>> result_dict.values() 
[{'comment': ['', 'slang'], 'language': 'fr', 'suggestion': ['manger', 'bouffer']}, {'comment': ['for animals', ''], 'language': 'de', 'suggestion': ['fressen', 'essen']}] 

基礎上main_key值,我們同所有其他人的字典在這個關鍵的名單。

1

使用reduce爲您提供了合併的完全分離和合並邏輯:

#!/usr/bin/env python 

from pprint import pprint 
from collections import defaultdict 

def group(grouped, ungrouped): 
    group = grouped[ungrouped['language']] 
    group['language'] = ungrouped['language'] 
    group['suggestion'].append(ungrouped['suggestion']) 
    group['comment'].append(ungrouped['comment']) 
    return grouped 

ungrouped = [{'language': 'de', 'suggestion': 'fressen', 'comment': 'for animals'}, 
      {'language': 'de', 'suggestion': 'essen', 'comment': ''}, 
      {'language': 'fr', 'suggestion': 'manger', 'comment': ''}, 
      {'language': 'fr', 'suggestion': 'bouffer', 'comment': 'slang'}] 

grouped = reduce(group, ungrouped, defaultdict(lambda: defaultdict(list))).values() 

# Convert defaultdict to dict for pretty printing. 
pprint([dict(group) for group in grouped]) 
+0

+1:雖然不是很pythonic,但它是一個非常實用的解決方案。 – phant0m

1

不是很Python的,但它也可以工作:

data = [{'language': 'de', 'suggestion': 'fressen', 'comment': 'for animals'}, 
{'language': 'de', 'suggestion': 'essen', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'manger', 'comment': ''}, 
{'language': 'fr', 'suggestion': 'bouffer', 'comment': 'slang'}] 

def prepare(inputData): 
    outputData = [] 
    if inputData and isinstance(inputData[0], dict) and inputData[0].get('language'): 
     keys = inputData[0].keys() 
     del keys[keys.index('language')] 
    else: 
     #do something - raise issue or return 
     return outputData 
    for l in set(line['language'] for line in inputData): 
     langData = {"language": l} 
     langData.update([(k, [line[k] for line in inputData if line["language"] == l]) for k in keys]) 
     outputData.append(langData) 
    return outputData 

prepare(data)