优雅的方法来删除列表中连续的重复元素?

mac*_*mac 4 python idioms list python-2.x

我正在寻找一种干净,Pythonic,从以下列表中消除的方法:

li = [0, 1, 2, 3, 3, 4, 3, 2, 2, 2, 1, 0, 0]
Run Code Online (Sandbox Code Playgroud)

所有连续的重复元素(运行长于一个数字),以获得:

re = [0, 1, 2, 4, 3, 1]
Run Code Online (Sandbox Code Playgroud)

但是虽然我有工作代码,感觉不是Pythonic,我很确定必须有一种方法(可能是一些鲜为人知的itertools功能?)以更加简洁和优雅的方式实现我想要的东西.

agf*_*agf 8

这是一个基于Karl的版本,它不需要列表的副本(tmp,切片和压缩列表).对于大型列表,izip它明显快于(Python 2)zip.chain比切片略慢但不需要tmp列表的对象或副本.islice加上一个tmp更快,但需要更多的内存,而不是优雅.

from itertools import izip, chain
[y for x, y, z in izip(chain((None, None), li), 
                       chain((None,), li), 
                       li) if x != y != z]
Run Code Online (Sandbox Code Playgroud)

一个timeit测试显示它是大约快两倍,卡尔的还是我的最快的groupby版本短群体.

如果您的列表可以包含s,请确保使用除None(如object())之外的值None.

如果您需要它来处理非序列的迭代器/可迭代,或者您的组很长,请使用此版本:

[key for key, group in groupby(li) 
        if (next(group) or True) and next(group, None) is None]
Run Code Online (Sandbox Code Playgroud)

timeit 显示它比1,000个项目组的其他版本快十倍.

早期,慢版本:

[key for key, group in groupby(li) if sum(1 for i in group) == 1]
[key for key, group in groupby(li) if len(tuple(group)) == 1]
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢`sum(1 for i in group)`但你的代码是正确的 (3认同)