将字典列表转换为唯一字典

时间:2018-10-06 13:46:45

标签: python python-3.x

我有:

[
  {'id': 1, 'name': 'foo'},
  {'id': 2, 'name': 'bar'},
  {'id': 1, 'name': 'gesiel'}
]

我想要:

{
  1: [
    {'id': 1, 'name': 'foo'},
    {'id': 1, 'name': 'gesiel'}
  ],
  2: [
    {'id': 2, 'name': 'bar'}
  ]
}

此代码执行以下操作:

organized = {d['id']:[] for d in data}
[organized[d['id']].append(d) for d in data]

还有更多的pythonic方法可以做到这一点吗?

4 个答案:

答案 0 :(得分:3)

使用collections.defaultdict

from collections import defaultdict

data = [{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}, {'id': 1, 'name': 'gesiel'}]

d = defaultdict(list)

for x in data:
    d[x['id']].append(x)

print(d)
# defaultdict(<class 'list'>, {1: [{'id': 1, 'name': 'foo'}, {'id': 1, 'name': 'gesiel'}], 2: [{'id': 2, 'name': 'bar'}]})

答案 1 :(得分:0)

使用 groupby.itertools 我们可以创建此字典

from itertools import groupby
lista = [{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}, {'id': 1, 'name': 'gesiel'}]

d = {}
for k, g in groupby(sorted(lista, key=lambda x: x['id']), key=lambda x: x['id']):
    d[k] = list(g)
# {1: [{'id': 1, 'name': 'foo'}, {'id': 1, 'name': 'gesiel'}], 2: [{'id': 2, 'name': 'bar'}]}

或使用字典理解

d = {k: list(g) for k, g in groupby(sorted(lista, key=lambda x: x['id']), key=lambda x: x['id'])}

答案 2 :(得分:0)

如果您正在使用内存对象,那么2遍O( n )解决方案没有什么问题。代码的主要问题是您滥用列表理解。

应该使用列表理解来构造一个新列表,而不是在循环中处理就地函数或方法。以您的示例为例,您的逻辑将创建一个类似于以下内容的列表:

[None, None, None, ..., None]

理解的副作用表示organized值具有根据需要附加的项目。相反,您可以使用简单的for循环进行重写:

organized = {d['id']: [] for d in data}

for d in data:
    organized[d['id']].append(d)

通过 not 通过初始迭代添加密钥,可以提高您的逻辑效率。与collections.defaultdict一样,@Austin's solution解决了这个常见问题。此解决方案为不存在的任何键提供了一个空列表:

from collections import defaultdict

res = defaultdict(list)

for d in data:
    res[d['i']].append(d)

print(res)

defaultdict(list,
            {1: [{'id': 1, 'name': 'foo'}, {'id': 1, 'name': 'gesiel'}],
             2: [{'id': 2, 'name': 'bar'}]})

由于defaultdictdict的子类,因此通常无需将其转换回常规字典。

答案 3 :(得分:0)

Austin's的答案更好,但是这里的方法仅使用dict s

In [175]: data = [{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}, {'id': 1, 'name': 'gesiel'}]

In [176]: organised = {}

In [177]: for d in data:
     ...:     if d['id'] in organised:
     ...:         organised[d['id']].append(d)
     ...:     else:
     ...:         organised[d['id']] = [d]
     ...:

In [178]: organised
Out[178]:
{1: [{'id': 1, 'name': 'foo'}, {'id': 1, 'name': 'gesiel'}],
 2: [{'id': 2, 'name': 'bar'}]}