单行创建列表字典

时间:2018-06-16 04:17:55

标签: python

如何做这个列表/字典理解 转此[("a", 1), ("b", 2), ("a", 3)]

进入这个

{
  "a": [1, 3],
  "b": [2]
}

我知道如何在for循环中执行此操作,我可以只使用一行来完成工作吗?

2 个答案:

答案 0 :(得分:4)

一种简单的方法是使用简单的collections.defaultdict()列表:

from collections import defaultdict

lst = [("a", 1), ("b", 2), ("a", 3)]

items = defaultdict(list)
for k, v in lst:
    items[k].append(v)

print(items)

创造了:

defaultdict(<class 'list'>, {'a': [1, 3], 'b': [2]})

注意:如果您希望最终结果是普通字典,则可以包裹dict()

如果你真的想要一个班轮,你可以在词典理解中使用itertools.groupby()

>>> from itertools import groupby
>>> from operator import itemgetter
>>> lst = [("a", 1), ("b", 2), ("a", 3)]
>>> {k: list(map(itemgetter(1), g)) for k, g in groupby(sorted(lst, key=itemgetter(0)), key=itemgetter(0))}
{'a': [1, 3], 'b': [2]}

也可以更清晰地写成:

{k: [x[1] for x in g] for k, g in groupby(sorted(lst, key=itemgetter(0)), key=itemgetter(0))}

由于排序,上述解决方案具有O(NlogN)复杂性,如果您想将类似项目组合在一起,则需要这样做。这比第一个defaultdict解决方案(O(N))效率低,因为您只需要迭代列表一次。第一种解决方案更为可取,因为它更易于阅读,高效和可维护。

答案 1 :(得分:2)

就我个人而言,我认为在这里使用循环是一个简单的选项,但为了演示,您可以在此处定义一个继承自 collections.MutableMapping 的自定义类来实现您的目标。

import collections

class AutoListDict(collections.MutableMapping):

  def __init__(self, values=()):            
      self.inner = collections.defaultdict(list)
      for k, v in values:
          self[k].append(v)

  def __setitem__(self, k, v): self.inner[k] = v
  def __getitem__(self, k):return self.inner[k]
  def __delitem__(self, k_): del self.inner[k]
  def __iter__(self): return iter(self.inner)
  def __len__(self): return len(self.inner)
  def __repr__(self): return str(dict(self.inner))

这会从您的输入值初始化 defaultdict ,因此不会覆盖附加到它的键。在操作中,您只需在元组数组上调用类构造函数:

>>> arr = [('a', 1), ('b', 2), ('a', 3)]
>>> AutoListDict(arr)
{'a': [1, 3], 'b': [2]}

或者如果你想要更类似于词典理解的东西:

>>> dct = AutoListDict((k, v) for k, v in arr)
>>> dct
{'a': [1, 3], 'b': [2]}