2016-02-03 169 views
1

我有字典,其中一些值是一个字符串列表,和其他值是整数:创建从字典列表一个新的字典在Python

list_countries = [{'country' : 'Suriname', 
      'population' : 532724, 
      'capital': 'Paramaribo', 
      'anthem': 'God zij met ons Suriname'}, 
      {'country' : 'Sweden', 
      'population' : 9683248, 
      'capital': 'Stockholm', 
      'anthem': 'Du gamla, Du fria'}, 
      ...] 

我想重塑每个这些键 - 值配对成一个大的新字典。然而,我的做法有问题:

dict_countries = { 'countries':  [], 
        'pop':    [], 
        'capital_city': [], 
        'national_anthem': [] } 

然后我遍历并与.extend()追加所有值。

for dictionary in list_countries: 
    dict_countries['countries'].extend(dictionary['country']) 
    dict_countries['pop'].extend(dictionary['population']) 
    dict_countries['capital_city'].extend(dictionary['capital']) 
    dict_countries['national_anthem'].extend(dictionary['anthem']) 

但是,这是行不通的。所有的字符串都是通过字母分开的。对于整数,我得到的错误:

TypeError: 'int' object is not iterable 

什么是正确的方法来做到这一点?

编辑:我相信每个键都有一个值。但是,假设没有。如果没有找到任何值,我将如何重写上述以添加NaN

+0

考虑当你确实想这样做。你的列表字典有点脆弱:如果任何列表不同步,整个事情就会变得混乱。另一种选择是由国家索引的字典。 –

+0

@ PM2Ring我将在一个pandas DataFrame中导入这本字典。也许我会重新提出这个问题,看看这是如何完成的。 – EB2127

回答

3

.extend()期望传递给它的参数是一个可迭代的,即。一个列表或一个字符串等。按照你的例子,​​是一个整数,因此不能迭代,因此你的异常信息。

如果将其更改为.append(),它的行为将与您期望的相同。

0

这是我所做的。唯一的限制是新词典中的键不是在语法上多元化的,但我想你可以在最后手动完成。

list_countries = [{'country' : 'Suriname', 
      'population' : 532724, 
      'capital': 'Paramaribo', 
      'anthem': 'God zij met ons Suriname'}, 
      {'country' : 'Sweden', 
      'population' : 9683248, 
      'capital': 'Stockholm', 
      'anthem': 'Du gamla, Du fria'}, 
      ] 


from collections import defaultdict 
d = defaultdict(list) 
for i in list_countries: 
    for k,v in i.items(): 
    d[k].append(v) 

d可以coverted回一个普通dict容易。

1

您得到输出结果的原因是因为列表上的appendextend之间存在差异。如果你的extend带有一个可迭代的参数(它是一个字符串),它会将迭代器中的每一项内联到字典中(这是字符串的每个字母)。然而它不能为int,因为这不是一个可迭代的。我宁愿使用append,它只是附加到字典中的列表。

list_countries = [{'country' : 'Suriname', 
      'population' : 532724, 
      'capital': 'Paramaribo', 
      'anthem': 'God zij met ons Suriname'}, 
      {'country' : 'Sweden', 
      'population' : 9683248, 
      'capital': 'Stockholm', 
      'anthem': 'Du gamla, Du fria'}] 

dict_countries = { 'countries':  [], 
        'pop':    [], 
        'capital_city': [], 
        'national_anthem': [] } 

for dictionary in list_countries: 
    dict_countries['countries'].append(dictionary['country']) 
    dict_countries['pop'].append(dictionary['population']) 
    dict_countries['capital_city'].append(dictionary['capital']) 
    dict_countries['national_anthem'].append(dictionary['anthem']) 

print dict_countries 
1

你有两个问题要解决这里:从你的字典中的值的
建立名单和翻译的旧密钥的新名称。

使用内置字典的setdefault方法和 使用翻译字典作为字面意义上的字典(即用于翻译)。

设置的翻译是这样的:

>>> translations = {'country': 'countries', 
...     'population': 'pop', 
...     'capital': 'capital_city', 
...     'anthem': 'national_anthem'} 

然后建立新的词典:

>>> merged = {} 
>>> for d in list_countries: 
...  for k in d: 
...   key = translations.get(k, k) 
...   merged.setdefault(key, []).append(d[k]) 
... 
>>> merged 
{'national_anthem': ['God zij met ons Suriname', 'Du gamla, Du fria'], 'capital_city': ['Paramaribo', 'Stockholm'], 'pop': [532724, 9683248], 'countries': ['Suriname', 'Sweden']} 

...如果你能确保所有的词典共享同一个密钥,这里有一个oneliner:

>>> {translations.get(k,k):[d[k] for d in list_countries] for k in list_countries[0].keys()} 
{'national_anthem': ['God zij met ons Suriname', 'Du gamla, Du fria'], 'capital_city': ['Paramaribo', 'Stockholm'], 'pop': [532724, 9683248], 'countries': ['Suriname', 'Sweden']} 
+0

你可以使用'collections.defaultdict'来避免'setdefault'(我发现它有点干净)。否则,很好的方法。 +1 – MariusSiuram

0
keys = list_countries[0].keys() 
values = (list(t) for t in zip(*[d.values() for d in list_countries])) 
dict(zip(keys, values)) 
+0

您不能保证字典将以相同的模式返回值。这是典型的实现,是的,但它不是字典的保证。所以你的方法可能会产生诸如“国家”之类的东西:['Suriname',12345,'France','Berlin']' – MariusSiuram

+0

Python文档声明:如果items(),keys(),values(),iteritems iterkeys()和itervalues()被调用时不会对字典进行中间修改,这些列表将直接对应。这允许使用zip()创建(值,键)对:pairs = zip(d.values(),d.keys())。 (https://docs.python.org/2/library/stdtypes.html#dict.items) – hayordi

+0

是的。要**相同的**字典。您正在将它用于多个字典。据我所知,没有保证。 – MariusSiuram