Python:如何通过对象属性过滤列表中的重复项?

Python:如何通过对象属性过滤列表中的重复项?

问题描述:

说我有Python:如何通过对象属性过滤列表中的重复项?

class a: 
    b = 1 
thing = a() 
thing2 = a() 
thing3 = a() 
thing3.b = 2 
lst = [thing,thing2,thing3] 

我想是这样的:

lst = filter_out(obj.b==obj2.b,lst) 

结果(与相同属性的对象进行筛选,以便只有一个左起):

[thing2,thing3]

这是如何实现的?据我所知,lambda过滤器不能用于比较列表中的两个对象。

+2

不应该是'[thing,thing2]'吗? –

+1

'Class'语法无效。它应该是'class'。 –

+0

@WillemVanOnsem我想删除重复的,过滤器部分有点混乱,所以我改变了 – Pear

使用字典来映射对象的b属性。由于字典不能包含两次b,字典的​​值将成为您独特的元素。

>>> unique = {} 
>>> for x in lst: 
...  unique[x.b] = x 
... 
>>> list(unique.values()) 
[<__main__.a object at 0xb724cfcc>, <__main__.a object at 0xb724cfec>] 

根据您是否要保留第一个或最后一个独特的项目,无论是覆盖现有值(如上面的代码)或添加项目之前添加if x.b not in unique检查。

+0

或者,如果你不想覆盖,请执行'unique.setdefault(xb,x)' – Artyer

可以使用,也groupbyitertools模块,像这样的例子:

from itertools import groupby 

class A: 
    b = 1 

thing = A() 
thing2 = A() 
thing3 = A() 
thing3.b = 2 
lst = [thing, thing2, thing3] 
# For testing purpose 
dct_id = {id(thing): "thing", id(thing2): "thing2", id(thing3): "thing3"} 
# groupping based on each object's b value 
sub = [list(v)[-1] for _, v in groupby(lst, lambda x: x.b)] 
# check the groupped objects by their id 
for k in sub: 
    print(dct_id[id(k)]) 

输出:

thing2 
thing3 

编辑:感谢@ tobias_k的评论

如果我们有这种物体:

thing = A() 
thing2 = A() 
thing3 = A() 
thing2.b = 2 
lst = [thing, thing2, thing3] 

为了避免不好的结果,我们需要通过其对象的b值sort lst。所以sub将变为:

sub = [list(v)[-1] for _, v in groupby(sorted(lst, key=lambda x: x.b), lambda x: x.b)] 

并重复同样的测试,我们将有:

thing3 
thing2 

PS:,最好在任何情况下进行排序sub列表,以避免不好的结果。

+1

'thing2.b = 2'而不是'thing3.b = 2'。这只适用于具有相同'key'值的元素彼此相邻的情况。 –

+0

@tobias_k好点!所以在这种情况下,我需要根据对象的b值对'lst'进行排序。查看我最近的更新。 –