有没有更符合Python风格的方法来防止向列表中添加重复项?

8

有没有更加Pythonic(或更简洁)的方法来防止向列表中添加重复元素?

if item not in item_list:
    item_list.append(item)

这实际上是一项廉价操作吗?

这是一个不错的选择,而且它也符合Pythonic风格。 - Siva Cn
6个回答

16

由于 @hcwsha 的原始解决方案已被替换,我在此记录:

seen = set(item_list)

# [...]

if item not in seen:
    seen.add(item)
    item_list.append(item)

这个运行时间为O(1),因此可以被认为比你目前使用的更好。


很好,这个像魔法一样有效,但我不明白为什么要使用.add和.append。我只是使用了“.add”并将集合转换为列表,使用list(seen)。 - Miguel Ortiz
2
@MiguelOrtiz 我猜你的项目顺序不重要。 - johnsyweb

4

您的方式非常好!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]

3
如果您有多个地方需要向集合中添加内容,写类似于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)

如果列表包含复杂的数据结构,那么这个解决方案非常优雅。 - arshovon

3

使用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])

0

当您在列表中拥有对象并需要检查某个属性以查看是否已经在列表中时。

不是说这是最好的解决方案,但它能胜任工作:

    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

0
你可以使用内置的set()函数如下所示,以及list()函数将该集合对象转换为普通的Python列表:
item_list = ['a','b','b']

print list(set(item_list))
#['a', 'b']

注意:使用集合时顺序不被保留。

你可能需要提到顺序可能无法保持。 - thefourtheye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接