删除列表中连续重复元素的优雅方法?
我正在寻找一种从以下列表中消除的干净的Pythonic方式:
I'm looking for a clean, Pythonic, way to eliminate from the following list:
li = [0, 1, 2, 3, 3, 4, 3, 2, 2, 2, 1, 0, 0]
所有连续的重复元素(运行超过一个数字)以获得:
all contiguous repeated elements (runs longer than one number) so as to obtain:
re = [0, 1, 2, 4, 3, 1]
但是,尽管我有工作代码,但感觉却不是Python风格的,我很确定必须有一种方法(也许是一些鲜为人知的itertools
函数?)以更简洁,更优雅的方式实现我想要的功能方式.
but although I have working code, it feels un-Pythonic and I am quite sure there must be a way out there (maybe some lesser known itertools
functions?) to achieve what I want in a far more concise and elegant way.
这里是基于Karl的版本,不需要列表的副本(tmp
,切片和压缩列表).对于大型列表,izip
明显比(Python 2)zip
快. chain
比切片稍慢一些,但不需要tmp
对象或列表副本. islice
加上制作tmp
的速度稍快一些,但是需要更多的内存并且不够优雅.
Here is a version based on Karl's which doesn't requires copies of the list (tmp
, the slices, and the zipped list). izip
is significantly faster than (Python 2) zip
for large lists. chain
is slightly slower than slicing but doesn't require a tmp
object or copies of the list. islice
plus making a tmp
is a bit faster, but requires more memory and is less elegant.
from itertools import izip, chain
[y for x, y, z in izip(chain((None, None), li),
chain((None,), li),
li) if x != y != z]
timeit
测试表明,它的速度大约是Karl或我最快的短组groupby
版本的两倍.
A timeit
test shows it to be approximately twice as fast as Karl's or my fastest groupby
version for short groups.
如果列表中可以包含None
,请确保使用除None
之外的其他值(例如object()
).
Make sure to use a value other than None
(like object()
) if your list can contain None
s.
如果您需要使用此版本来处理不是序列的迭代器/可迭代,或者您的组很长,请使用此版本:
Use this version if you need it to work on an iterator / iterable that isn't a sequence, or your groups are long:
[key for key, group in groupby(li)
if (next(group) or True) and next(group, None) is None]
timeit
显示,对于1,000个项目组,它比另一个版本快大约十倍.
timeit
shows it's about ten times faster than the other version for 1,000 item groups.
早期,慢速版本:
[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]