这是传统方式,原位删除相邻的重复项,同时向后遍历列表:
Python 1.5.2 (#0, Apr 13 1999, 10:51:12) [MSC 32 bit (Intel)] on win32
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> def dedupe_adjacent(alist):
... for i in xrange(len(alist) - 1, 0, -1):
... if alist[i] == alist[i-1]:
... del alist[i]
...
>>> data = [1,2,2,3,2,2,4]; dedupe_adjacent(data); print data
[1, 2, 3, 2, 4]
>>> data = []; dedupe_adjacent(data); print data
[]
>>> data = [2]; dedupe_adjacent(data); print data
[2]
>>> data = [2,2]; dedupe_adjacent(data); print data
[2]
>>> data = [2,3]; dedupe_adjacent(data); print data
[2, 3]
>>> data = [2,2,2,2,2]; dedupe_adjacent(data); print data
[2]
>>>
更新:如果您想要一个生成器,但(没有 itertools.groupby 或(您可以比阅读它的文档并理解它的默认行为更快地键入)),这里有六个 -完成这项工作的班轮:
Python 2.3.5 (#62, Feb 8 2005, 16:23:02) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> def dedupe_adjacent(iterable):
... prev = object()
... for item in iterable:
... if item != prev:
... prev = item
... yield item
...
>>> data = [1,2,2,3,2,2,4]; print list(dedupe_adjacent(data))
[1, 2, 3, 2, 4]
>>>
更新 2:关于巴洛克风格的itertools.groupby() 和极简主义的object() ...
要消除 itertools.groupby() 的 dedupe_adjacent 效果,您需要在其周围包裹一个列表推导以丢弃不需要的分组:
>>> [k for k, g in itertools.groupby([1,2,2,3,2,2,4])]
[1, 2, 3, 2, 4]
>>>
... 或与itertools.imap 和/或operators.itemgetter 混在一起,如另一个答案所示。
object 实例的预期行为是,它们中的任何一个都不等于任何类的任何其他实例,包括 object 本身。因此,它们作为哨兵非常有用。
>>> object() == object()
False
值得注意的是,itertools.groupby 的 Python reference code 使用 object() 作为标记:
self.tgtkey = self.currkey = self.currvalue = object()
当您运行该代码时,它会做正确的事情:
>>> data = [object(), object()]
>>> data
[<object object at 0x00BBF098>, <object object at 0x00BBF050>]
>>> [k for k, g in groupby(data)]
[<object object at 0x00BBF098>, <object object at 0x00BBF050>]
更新3:关于正向索引原位操作的说明
OP 修改后的代码:
def remove_adjacent(nums):
i = 1
while i < len(nums):
if nums[i] == nums[i-1]:
nums.pop(i)
i -= 1
i += 1
return nums
最好写成:
def remove_adjacent(seq): # works on any sequence, not just on numbers
i = 1
n = len(seq)
while i < n: # avoid calling len(seq) each time around
if seq[i] == seq[i-1]:
del seq[i]
# value returned by seq.pop(i) is ignored; slower than del seq[i]
n -= 1
else:
i += 1
#### return seq #### don't do this
# function acts in situ; should follow convention and return None