如何检查和删除字典中项目的重复值?
我有一个大型数据集,所以我正在寻找一种有效的方法。 以下是包含副本的字典中的值的示例:
1'word': [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]
需要成为
1'word': [('769817', [6]), ('769819', [4, 10])]
你的问题中没有python字典,只有整数和字符串,列表和元组。 你是什么意思"字典"?
示例是字典中的项目的值,我必须显示它包含的内容
这是stackoverflow.com/questions/2931672/的副本
再次,我不是只使用列表!
这个问题基本上归结为从不可用类型列表中删除重复项,为此无法转换为集合。
一种可能的方法是在构建新列表值时检查当前值的成员资格。
1
2
3
4
5
6
7d = {'word': [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]}
for k, v in d.items():
new_list = []
for item in v:
if item not in new_list:
new_list.append(item)
d[k] = new_list
或者,使用groupby()获得更简洁的答案,尽管可能更慢(列表必须先排序,如果是,那么它比进行成员资格检查更快)。
1
2
3
4
5
6import itertools
d = {'word': [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]}
for k, v in d.items():
v.sort()
d[k] = [item for item, _ in itertools.groupby(v)]
输出 - > {'word': [('769817', [6]), ('769819', [4, 10])]}
谢谢你的作品!
添加了另一种方法,我将探索两种方法的基准标记,以查看哪些方法可以更好地使用您的数据集。
@mrdomoboto:为什么list()包装genexpr?无论如何,[item for item, _ in itertools.groupby(v)]将比传递给list构造函数的genexpr更快/更简洁。此外,如果list未排序,groupby只会慢一些;如果它已经排序,如在例子中,不需要排序,所以它实际上比理论上的任何其他解决方案更快(O(n)没有有意义的常数因子)。如果需要通过将理解改为list(map(operator.itemgetter(0), itertools.groupby(v)))(list()包装仅为Py3)将所有工作推送到C层,它可以进一步优化。
你是对的,list()包装器确实为该行增加了另一个数量级的成本。我更新了我的答案。是的,如果列表已经排序,groupby()会快得多,这就是我添加注释的原因。
那个怎么样?
1
2
3
4
5
6
7
8def remove_duplicates(d: dict):
unique_values = set(d.values())
o = {}
for k, v in d.items():
if v in unique_values:
o[k] = v
unique_values.remove(v)
return o
您可以根据它们生成的哈希来对项目进行统一。哈希可以是任何东西,排序json.dumps或cPickle.dumps。
这个班轮可以根据需要统一你的词典。
1
2
3
4>>> d = {'word': [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]}
>>> import json
>>> { k: { json.dumps(x,sort_keys = True):x for x in v}.values() for k,v in d.iteritems()}
{'word': [('769817', [6]), ('769819', [4, 10])]}
这个怎么样:
我只关注列表部分:
1
2
3
4>>> s = [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]
>>> [(x,y) for x,y in {key: value for (key, value) in s}.items()]
[('769817', [6]), ('769819', [4, 10])]
>>>
该列表理解可简化为:dict(s).items()(Py3上的list(dict(s).items()))。当数据已经是构造函数所期望的数据时,无需将所有内容都变成理解。它也只能通过tuple中的第一个元素而不是第二个元素进行统一,并且不保留顺序,这可能与要求不匹配。如果这是可以接受的,它的效率。
这非常周到,效率更高。
Strikethrough在编辑之前应用于原始问题,留给子孙后代:
你根本不使用dict,只是list的两个tuple,其中每个tuple中的第二个元素本身是list。如果你真的想要dict,
1dict([('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])])
将它转换,并通过键进行统一(因此你最终会得到{'769817': [6], '769819': [4, 10]},虽然它会失去秩序,并且不会注意值(sub list s)是否唯一(it)只保留给定密钥的最后一个配对。 s>
如果你需要在保留顺序的同时统一相邻的重复项(值对唯一性很重要),并且不需要/需要真正的dict,请使用itertools.groupby:
1
2
3
4
5
6
7import itertools
nonuniq = [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]
uniq = [k for k, g in itertools.groupby(nonuniq)]
# uniq is [('769817', [6]), ('769819', [4, 10])]
# but it wouldn't work if the input was
# [('769819', [4, 10]), ('769817', [6]), ('769819', [4, 10])]
# because the duplicates aren't adjacent
如果您需要折叠不相邻的重复项,并且不需要保留顺序(或排序顺序很好),您可以使用groupby来获取O(n log n)解决方案(而不是创建新列表的天真解决方案)并通过检查O(n^2)复杂度的新列表中的存在,或基于set的解决方案O(n)但要求您将数据中的sub list转换为tuple来避免重复他们可以洗):
1
2
3# Only difference is sorting nonuniq before grouping
uniq = [k for k, g in itertools.groupby(sorted(nonuniq))]
# uniq is [('769817', [6]), ('769819', [4, 10])]
我正在使用字典。我有1个键的多个元组
@Brutalized:你原来的问题没有说清楚。在任何情况下,最后两个选项是当前接受的答案的更优化版本(如果数据已经订购,非排序groupby是O(n),如果需要排序,则其O(n log n),两者都是是对list循环的一个重大改进,list包含每次迭代的检查。
你有一个列表,而不是字典。 Python字典可能只有每个键的一个值。尝试
1my_dict = dict([('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])])
结果:
1{'769817': [6], '769819': [4, 10]}
一本Python字典。有关更多信息,请访问https://docs.python.org/3/tutorial/datastructures.html#dictionaries
这不会返回列表。
我确实有多个项目作为价值
1
2
3
4
5
6
7your_list = [('769817', [6]), ('769819', [4, 10]), ('769819', [4, 10])]
new = []
for x in your_list:
if x not in new: new.append(x)
print(new)
>>>[('769817', [6]), ('769819', [4, 10])]
这是对列表理解的可怕滥用。不要使用list理解副作用。它们是一个功能构造,功能代码是无副作用的;使用它们来产生副作用是浪费的(造成list的垃圾list,之后被扔掉)并且令人困惑。只需对这些情况使用普通的for循环。另外,永远不要命名变量list;阴影内置是一种可怕的做法。
@ShadowRanger我修好了。
你做了,但新代码在一般情况下有自己的问题(对于两个tuple情况确实没有问题),因为错误的值会被该测试误认为重复(a list喜欢[1, None, 0, 2],没有重复的,仍然会减少到[1, 2],因为None和0看起来像这个逻辑的重复。您可以执行if x not in new: new.append(x)并避免to_append临时,并且可能会混淆重复值的伪值。
@ShadowRanger thx,固定。
投票已被删除。 :-)