提问人:joseville 提问时间:11/6/2022 更新时间:11/6/2022 访问量:111
从列表中删除重复的可变对象
Remove duplicate mutable objects from a list
问:
当我有一个不可变对象的列表,并且想要摆脱重复项时,我可以使用:lst
set(lst)
lst = [0,4,2,6,3,6,4,9,2,2] # integers are immutable in python
print(set(lst)) # {0,2,3,4,6,9}
但是,假设我有一个可变对象列表,并且想要删除重复项。 不会起作用,因为可变对象不可散列 - 我们会得到一个 .在这种情况下,我们应该怎么做?lst
set(lst)
TypeError: unhashable type: '<type>'
例如,假设我们有 ,一个 s 列表(s 是可变的,因此不可散列),并且有些在 中多次出现:lst
dict
dict
dicts
lst
d0 = {0:'a', 1:'b', 9:'j'}
d1 = {'jan':1, 'jul':7, 'dec':12}
d2 = {'hello':'hola', 'goodbye':'adios', 'happy':'feliz', 'sad':'triste'}
lst = [d0, d1, d1, d0, d2, d1, d0]
我们想遍历,但只考虑一次。如果我们这样做,我们会得到一个 .相反,我们必须做这样的事情:lst
dict
set(lst)
TypeError: unhashable type: 'dict'
def dedup(lst):
seen_ids = set()
for elem in lst:
id_ = id(elem)
if id_ not in seen_ids:
seen_ids.add(id_)
yield elem
有没有更好的方法可以做到这一点???
答:
1赞
chrslg
11/6/2022
#1
好吧,您可以使用带有 id 的 dict 作为键。这是大致相同的想法,但允许像这样的单行。
list({id(x):x for x in lst}.values())
评论
0赞
0x0fba
11/6/2022
如果将内容与 相同的字典添加到字典中,则不再起作用。lst
d3
d0
0赞
chrslg
11/6/2022
@fbattello确实如此。但在我看来,这似乎是这个问题的一个假设。我看到,在另一条评论中,您理解这个问题有深刻的比较。我没有,我承认不清楚。在最后的评论之后,我仍然不确定(它们似乎表明,我们确实希望根据其内容删除重复项。但甚至不确定这些是岛屿,还是索引列表或......但实际上,如果我们想从内容中删除重复项,您的答案就是其中之一(如果有循环或类似的东西,它将不起作用)。如果没有,那就太慢了。
-1赞
user3435121
11/6/2022
#2
此方法使用 2 个列表:ID 列表和元素列表。
d0 = {0:'a', 1:'b', 9:'j'}
d1 = {'jan':1, 'jul':7, 'dec':12}
d2 = {'hello':'hola', 'goodbye':'adios', 'happy':'feliz', 'sad':'triste'}
lst = [d0, d1, d1, d0, d2, d1, d0]
def dedup( lst):
id_seen = []
elems = []
for elem in lst:
if id(elem) not in id_seen:
id_seen.append( id(elem))
elems.append( elem)
return elems
print( dedup( lst))
评论
2赞
mkrieger1
11/6/2022
与问题中已经显示的内容相比,这有什么改进?
3赞
0x0fba
11/6/2022
#3
使用对象 ID 非常危险。
如果您有两个内容相同的字典,则它不再起作用。
您可以使用该模块将字典序列化为字符串。json
import json
def dedup(lst):
myset = {json.dumps(x) for x in lst} # serialize to a set
return [json.loads(x) for x in myset] # deserialize to the list
评论
3赞
mkrieger1
11/6/2022
目前尚不清楚是否需要一种或另一种行为。
1赞
0x0fba
11/6/2022
根据问题,问题是为不可散列的对象(示例中的字典)找到解决方案。如果它们是可散列的,则具有相同内容的两个对象将具有相同的散列值,因此将相等。在我的理解中,首选的行为是,如果两个对象的内容相等,则解决方案必须将两个对象视为相等。
1赞
0x0fba
11/6/2022
d0 = {0:'a', 1:'b', 9:'j'} d3 = {0:'a', 1:'b', 9:'j'} id(d0) == id(d3) # False d0 == d3 # True
评论
groups
groups[i]