如何将字典列表转换为字典

79

如何将字典列表转换为字典。以下是字典列表:

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
to
data = {'John Doe': {'name': 'John Doe', 'age': 37, 'sex': 'M'},
        'Lisa Simpson': {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        'Bill Clinton': {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}}

1
尝试将你的第二行代码放入一个Python脚本中并运行它。它能正常运行吗?我觉得不行... - Platinum Azure
29
您的问题在发布时并不太明确。您希望字典的键和相关值是什么?您写的第二件事不是有效的Python对象。 - dfan
http://docs.python.org/tutorial/datastructures.html#dictionaries - Ignacio Vazquez-Abrams
3
你希望输出的不是一个字典,而是一个集合!也许需要修改问题以避免混淆。 - gavin
9个回答

104

一种使用名称作为新键的可能解决方案:

new_dict = {}
for item in data:
   name = item['name']
   new_dict[name] = item

使用Python 3.x,你也可以使用字典推导式来以更简洁的方式实现相同的方法:

new_dict = {item['name']:item for item in data}

如Paul McGuire在评论中建议的那样,如果你不想在内部字典中包含名称,可以执行以下操作:

new_dict = {}
for item in data:
   name = item.pop('name')
   new_dict[name] = item

4
这将留下一个额外的姓名字段,这可能是用户想要的,也可能不是。(即,新字典看起来像{'Lisa Simpson': {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'} ...} - Platinum Azure
1
在分配名称后添加“item.pop('name')”,那么您就不会得到多余的名称字段。 - PaulMcG
2
@Platinum - 当使用字典作为查找表时,这实际上是非常常见的。另一个数据结构可以直接引用字典值,而不会丢失键(与每次存储键并在访问时查找表中的键相反)。 - Ben Blank
2
@Platinum Azure:你说得对,但是OP的问题没有给出任何关于这方面的线索。这只是一个可能的解决方案。当我想要使用主题信息中的值来获取完整信息时,我在一些应用程序中使用了类似的字典(使用冗余字段)。显然,也可以使用其他主键,或者像建议的那样,从原始字典中消除冗余键。 - joaquin
如果数据是动态的,并且没有固定的“name”键,该怎么办?有解决方法吗?我的情况与此类似,但是我的数据由MongoDB查询组成,因此不是静态的。 - user5512021
问题很简单,就是将一个字典列表转换为一个字典。我认为所建议的解决方案并没有产生预期的输出。 - Srinivas

55

python 3.3 版本开始,您可以使用 ChainMap

ChainMap将多个字典或其他映射组合在一起,创建一个可更新的单一视图。如果没有指定映射,则提供一个空字典,以便新链始终至少有一个映射。

from collections import ChainMap

data = dict(ChainMap(*data))

1
这个是否保证更快?之前的答案对整个列表进行迭代,因此是O(n),ChainMap比这个更少吗? - gudé
21
它仅将行的第一个条目作为字典返回。 - Abdul Haseeb
请注意,正如@gudé所评论的那样,ChainMap并不高效。 - C.K.

40

如果字典不共享键,则可以使用:

dict((key,d[key]) for d in data for key in d)

也许在你的情况下,生成一个以列表为值的字典会更好?

newdict={}
for k,v in [(key,d[key]) for d in data for key in d]:
  if k not in newdict: newdict[k]=[v]
  else: newdict[k].append(v)
这将产生:
>>> newdict
`{'age': [37, 17, 57], 'name': ['John Doe', 'Lisa Simpson', 'Bill Clinton'], 'sex': ['M', 'F', 'M']}`

15

尝试这种方法:

{key: val} for k in data for key, val in k.items())

6

我们不要过于复杂化这个问题:

simple_dictionary = dict(data[0])

这不是解决方案,但它对我的问题有所帮助,所以我会点赞。 - Zesty Dragon

2
也许你希望以名称为键?由于第二个示例无效且没有实际意义,因此您没有明确指定。

请注意,我的示例从值中删除了键“名称”,这可能是可取的(或者也可能不是)。

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
newdata = {}
for entry in data:
    name = entry.pop('name') #remove and return the name field to use as a key
    newdata[name] = entry
print newdata
##{'Bill Clinton': {'age': 57, 'sex': 'M'},
## 'John Doe': {'age': 37, 'sex': 'M'},
## 'Lisa Simpson': {'age': 17, 'sex': 'F'}}
print newdata['John Doe']['age']
## 37

这取决于你如何解释辛普森时光。毕竟,如果她在1989年节目开始时是8岁,那么今天她就会是29或30岁... :-) - Ben Blank

1

我的意见,不喜欢任何一个答案:

from functools import reduce
collection = [{'hello': 1}, {'world': 2}]
answer = reduce(lambda aggr, new: aggr.update(new) or aggr, collection, {})

这种方法的输出将会是什么,这个问题只回答了一半。 - undefined
@basquiatraphaeu 这将会将所有字典按顺序合并,并进行更新。 - undefined

1
import pandas as pd
data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]

print(pd.DataFrame(data).to_dict())

Pandas 在这里似乎有些大材小用。 - OneCricketeer

0

如果您想要一个功能性的替代方案(也假设名称作为新键是需要的),您可以这样做

from toolz.curried import *

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]

newdata = pipe(data, 
               map(lambda x: {x['name']: dissoc(x, 'name')}),
               lambda x: merge(*x)
)

print(newdata)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接