简体   繁体   English

将dicts列表转换为唯一的dict

[英]Convert list of dicts into a unique dict

I have: 我有:

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

I want: 我想要:

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

This code does this: 这段代码执行此操作:

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

Is there a more pythonic way to do this? 是否有更多的pythonic方式来做到这一点?

Use collections.defaultdict : 使用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'}]})

Using groupby.itertools we can create this dicitonary 使用groupby.itertools我们可以创建这个dicitonary

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'}]}

or using dictionary comprehension 或使用字典理解

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

There is nothing wrong with a 2-pass O( n ) solution if you are, as here, working with an in-memory object. 如果你在这里使用内存中的对象,那么2遍O( n )解决方案没有任何问题。 The main issue with your code is you are misusing the list comprehension. 您的代码的主要问题是您滥用列表理解。

A list comprehension should be used to construct a new list, not to process an in-place function or method in a loop. 应使用列表推导来构造新列表,而不是在循环中处理就地函数或方法。 Taking your example, your logic will create a list which looks like: 举个例子,你的逻辑将创建一个如下所示的列表:

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

The side-effect of the comprehension means that organized values have items appended to them as required. 理解的副作用意味着organized值根据需要附加了项目。 Instead, you can rewrite using a simple for loop: 相反,您可以使用简单的for循环重写:

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

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

Your logic can be made more efficient by not adding keys via an initial iteration. 通过通过初始迭代添加键,可以提高逻辑效率。 This common problem is resolved by collections.defaultdict , as in @Austin's solution . 这个常见问题由collections.defaultdict解决,就像在@Austin的解决方案中一样 This solution gives an empty list for any key which does not exist: 此解决方案为任何不存在的键提供一个空列表:

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'}]})

Since defaultdict is a subclass of dict , there's usually no need to convert this back to a regular dictionary. 由于defaultdictdict的子类,因此通常无需将其转换回常规字典。

Austin's answer is better, but here method just using dict 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'}]}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM