从字典的迭代中删除“无”

时间:2019-09-16 08:26:50

标签: python python-3.x dictionary

我有一个包含各种键和值的词典列表。我试图根据键对其进行分组

from itertools import chain, zip_longest 

data = [
    {'a': 2, 'b': 4, 'c': 3, 'd': 2},   
    {'b': 2, 'c': 2, 'd': 5, 'e': 4, 'f': 1},
    {'a': 2, 'd': 2, 'e': 6, 'f': 5, 'g': 12},
    {'b': 2, 'd': 2, 'e': 6, 'f': 6},
    {'c': 5, 'e': 33, 'g': 21, 'h': 56, 'i': 21}
    ]

print(type(data))

bar ={
    k: [d.get(k) for d in data]
    for k in chain.from_iterable(data)
}

print(bar)

我的输出:

{'a': [2, None, 2, None, None], 'b': [4, 2, None, 2, None], 
'c': [3, 2, None, None, 5], 'd':[2, 5, 2, 2, None], 'e': [None, 4, 6, 6, 33], 
'f': [None, 1, 5, 6, None], 'g': [None, None, 12, None, 21], 
'h': [None, None, None, None, 56], 'i': [None, None, None, None, 21]}

我不想在值中显示“无”

所需的输出:

 {'a': [2, 2], 'b': [4, 2, 2], 'c': [3, 2, 5], 'd':[2, 5, 2, 2], 'e': [4, 6, 6, 33], 
'f': [1, 5, 6], 'g': [1221], 'h': [56], 'i': [21]}

我也尝试使用过滤器功能,但没有成功。有关如何删除无的任何指导?

Code

6 个答案:

答案 0 :(得分:3)

尝试this

from operator import is_not
from functools import partial

{ k: list(filter(partial(is_not, None), v)) for k, v in d.items() }
  

输入:{'x':[0,23,234,89,None,0,35,9]}

     

输出: {'x':[0,23,234,89,0,35,9]}

答案 1 :(得分:1)

您可以使用filter(None, x)删除None

filter(None, [3, 4, None, 2, 7, None, 1])
[3, 4, 2, 7, 1]

要使所有字典值具有该值,请使用以下理解:

{ k: filter(None, v) for k, v in d.items() }

(在Python 2中使用.iteritems()。)

请记住,在Python 3中,filter函数会生成可以廉价迭代的惰性过滤器对象。要将它们转换为list,只需使用list(filter(...))

但是最好不要首先引入None值:

r = {}
for d in data:
  for k, v in d.items():
    r.setdefault(k, []).append(v)
print(r)

答案 2 :(得分:1)

如果您想使用代码,则可以执行以下操作:

bar ={
    k: [d.get(k) for d in data if d.get(k) != None]
    for k in chain.from_iterable(data)
}

print(bar)

输出:

{'a': [2, 2], 'b': [4, 2, 2], 'c': [3, 2, 5], 'd': [2, 5, 2, 2], 'e': [4, 6, 6, 33], 'f': [1, 5, 6], 'g': [12, 21], 'h': [56], 'i': [21]}

答案 3 :(得分:1)

当字典的get函数的键不存在时,它们将返回None。您可以简单地使用if条件来确保该值存在。

bar = {k: [d[k] for d in data if d.get(k) is not None] for k in chain.from_iterable(data)}

如果您的词典非常大,其中包含很多None值,则双重查找将非常昂贵。因此,您可以改用过滤器。

bar = {k: list(filter(None, [d.get(k) for d in data])) for k in chain.from_iterable(data)}

答案 4 :(得分:1)

大多数提供的解决方案都集中在使OP方法具有复杂的理解力上。我认为在这种情况下,有必要将循环拆分为不同的行,而不是使用理解。

data = [...]

bar = {}
for my_dict in data:
   for key, value in my_dict.items():
      bar.setdefault(key, []).append(value)

print(bar)

答案 5 :(得分:1)

如果不存在密钥,则不要使用get并返回None,而要使用d[k],而是先检查是否k in d。另外,我建议不要使用chain,因为那样会计算许多列表两次或更多次,每次都覆盖先前创建的列表,因为多个字典中都存在许多键。相反,您可以迭代所有键中的set

>>> {k: [d[k] for d in data if k in d]
...  for k in set(k for d in data for k in d)}
...
{'a': [2, 2], 'b': [4, 2, 2],
 'c': [3, 2, 5], 'd': [2, 5, 2, 2],
 'e': [4, 6, 6, 33], 'f': [1, 5, 6],
 'g': [12, 21], 'h': [56], 'i': [21]}