有没有更加Pythonic(或更简洁)的方法来防止向列表中添加重复元素?
if item not in item_list:
item_list.append(item)
这实际上是一项廉价操作吗?
由于 @hcwsha 的原始解决方案已被替换,我在此记录:
seen = set(item_list)
# [...]
if item not in seen:
seen.add(item)
item_list.append(item)
这个运行时间为O(1),因此可以被认为比你目前使用的更好。
您的方式非常好!Set在这种情况下非常有用,但正如之前提到的那样,它们无法保持顺序。其他写法更加简洁,尽管可能不太清晰,如下所示:
item_list.append(item) if item not in item_list else None
并且
item_list += [item] if item not in item_list else []
new_items = [item1, ...]
来改编。item_list += [item for item in new_items if item not in item_list]
if item not in item_list...
这样的样板代码并不是十分方便。解决此问题的方式是要么编写一个单独的函数来跟踪对集合的更改,要么通过子类化列表并重写'append'方法来实现。class CollisionsList(list):
def append(self, other):
if other in self:
raise ValueError('--> Value already added: {0}'.format(other))
super().append(other)
l = CollisionsList()
l.append('a')
l.append('b')
l.append('a')
print(l)
使用set
来跟踪已经看过的项目,集合提供了O(1)
的查找速度。
>>> item_list = [1, 7, 7, 7, 11, 14 ,100, 100, 4, 4, 4]
>>> seen = set()
>>> item_list[:] = [item for item in item_list
if item not in seen and not seen.add(item)]
>>> item_list
[1, 7, 11, 14, 100, 4]
item_list
上使用 set()
:>>> set(item_list)
set([1, 100, 7, 11, 14, 4])
当您在列表中拥有对象并需要检查某个属性以查看是否已经在列表中时。
不是说这是最好的解决方案,但它能胜任工作:
def _extend_object_list_prevent_duplicates(list_to_extend, sequence_to_add, unique_attr):
"""
Extends list_to_extend with sequence_to_add (of objects), preventing duplicate values. Uses unique_attr to distinguish between objects.
"""
objects_currently_in_list = {getattr(obj, unique_attr) for obj in list_to_extend}
for obj_to_add in sequence_to_add:
obj_identifier = getattr(obj_to_add, unique_attr)
if obj_identifier not in objects_currently_in_list:
list_to_extend.append(obj_to_add)
return list_to_extend
set()
函数如下所示,以及list()
函数将该集合对象转换为普通的Python列表:item_list = ['a','b','b']
print list(set(item_list))
#['a', 'b']