我在
Python 3.5.2中有一个字典列表,我试图“重复数据删除”.所有字典都是唯一的,但是有一个特定的键我想要重复删除,保持字典具有最多的非空值.
例如,我有以下字典列表:
d1 = {"id":"a", "foo":"bar", "baz":"bat"}
d2 = {"id":"b", "foo":"bar", "baz":None}
d3 = {"id":"a", "foo":"bar", "baz":None}
d4 = {"id":"b", "foo":"bar", "baz":"bat"}
l = [d1, d2, d3, d4]
我想将l过滤到只有具有唯一id键的字典,保持具有最少空值的字典.在这种情况下,函数应该保持d1和d4.
我试图创建一个新的键,val对“值计数”,如下所示:
for d in l:
d['val_count'] = len(set([v for v in d.values() if v]))
现在我要坚持的是如何过滤我的唯一ID的dicts列表,其中val_count键是更大的值.
我对其他方法持开放态度,但由于资源限制,我无法将pandas用于此项目.
预期产量:
l = [{"id":"a", "foo":"bar", "baz":"bat"},
{"id":"b", "foo":"bar", "baz":"bat"}]
最佳答案 我会使用
groupby并从每组中选择第一个:
1)首先按键排序(创建组)和减少空值计数(您的既定目标):
>>> l2=sorted(l, key=lambda d: (d['id'], -sum(1 for v in d.values() if v)))
2)然后按ID分组,并在排序列表的groupby中将每个迭代器的第一个元素显示为d:
>>> from itertools import groupby
>>> [next(d) for _,d in groupby(l2, key=lambda _d: _d['id'])]
[{'id': 'a', 'foo': 'bar', 'baz': 'bat'}, {'id': 'b', 'foo': 'bar', 'baz': 'bat'}]
如果你想要一个’tie breaker’来选择第一个dict,否则它们具有相同的空值,你可以添加一个枚举装饰器:
>>> l2=sorted(enumerate(l), key=lambda t: (t[1]['id'], t[0], -sum(1 for v in t[1].values() if v)))
>>> [next(d)[1] for _,d in groupby(l2, key=lambda t: t[1]['id'])]
我怀疑是否需要额外的步骤,因为Python的排序(和排序)是stable sort,并且序列将仅根据键和空值计数从列表顺序更改.因此,除非您确定需要使用第二个版本,否则请使用第一个版本.