只有当前迭代元素不在列表中时,才必须将元素附加到列表中。
>>> l = [1, 2]
>>> for x in (2, 3, 4):
... if x not in l:
... l.append(x)
...
>>> l
[1, 2, 3, 4]
VS
>>> l = [1, 2]
>>> [l.append(i) for i in (2, 3, 4) if i not in l]
[None, None]
>>> l
[1, 2, 3, 4]
列表理解给出了我想要的结果,只是返回的列表是没用的。这是列表推导的一个很好的用例吗?
迭代是一个很好的解决方案,但我想知道是否有更惯用的方法来做到这一点?
答案 0 :(得分:7)
无论是否有列表推导,此算法都不尽可能高效; list.__contains__
是O(n),因此将另一个列表的元素添加到其中是O(n 2 )。另一方面,set.__contains__
是O(log n),因此最佳方法是使用集合来检查成员资格,使用列表来保留顺序。这样你就可以进行O(log n)的n次操作,总共为O(n log n),比O(n 2 )快得多,合理的n值(以上)比方说,100个元素。)
>>> l = [1, 2]
>>> seen = set(l)
>>> for x in (2, 3, 4):
... if x not in seen:
... seen.add(x)
... l.append(x)
...
>>> l
[1, 2, 3, 4]
>>>
答案 1 :(得分:5)
你可以这样做:
l.extend((i for i in (2,3,4) if i not in l))
如果添加的列表不唯一,此解决方案仍然有效。
答案 2 :(得分:3)
不建议仅针对副作用使用列表推导。 3行版本没有任何问题。
如果l
变得非常长,您可能希望并行维护一个集合以避免在长列表中使用in l
答案 3 :(得分:3)
我可以建议另外一个解决方案:
orig = [1,2]
ext = [2,3,4]
orig.extend(filter( lambda x,p=set(orig):not(x in p or p.add(x)),ext ))
它考虑了元素顺序,并在元素重复的情况下起作用。
BTW,复杂度为O(n * log(n))。