在Python中替换列表中的重复元素?

2024-03-28 23:22:29 发布

您现在位置:Python中文网/ 问答频道 /正文

例如,如果我有如下列表:

[3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]

我如何删除重复的元素并表示同一个元素,后跟它的重复次数? 输出示例:

^{pr2}$

其中3是重复6次。。。 1重复6次。。。等等


Tags: 元素示例列表次数pr2
3条回答

不使用itertools的替代解决方案是:

my_list = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
new_list = []

new_list.append(my_list[0]) #adding first element

count = 1 #variable for counting repeated elements
i = 1 #iterator through list

l = len(my_list)

while i < l:
    while i < l and my_list[i] == my_list[i-1]:
        count +=1
        i+=1
    if count > 1:
        new_list.append(count)
        count = 1 #returning to original default value
    else:
        new_list.append(my_list[i])
        i+=1

print(new_list)

您可以在此处将^{}与生成器函数一起使用:

>>> from itertools import groupby                                              
>>> lst = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
>>> def solve(seq):
    for k, g in groupby(seq):
        length = sum(1 for _ in g)
        if length > 1:
            yield k
            yield length
        else:
            yield  k
...             
>>> list(solve(lst))
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]

itertools是最好的解决方案,但是对于没有导入的另一种方法,我们可以使用dict:

od = {}

prev = None
out = []
for ele in l:
    if ele != prev and prev in od:
        out.extend((prev, od[prev])) if od[prev] > 1 else out.append(prev)
        od[prev] = 0
    od.setdefault(ele, 0)
    od[ele] += 1
    prev = ele
out.extend((ele, od[ele])) if od[ele] > 1 else out.append(ele)
print(out)
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]

或者在使用更高效的defaultdict的函数中,在dict中存储数据需要更多内存,但使用groupby可能是更快的解决方案:

^{pr2}$

有趣的是,这是一个很好的速度,可能是因为我们不必循环每个子列表来获得len:

In [33]: l = [choice(l) for _ in range(100000)]

In [34]: timeit grp1(l)
10 loops, best of 3: 23.9 ms per loop

In [35]: timeit list(solve(l))
10 loops, best of 3: 33.9 ms per loop

In [36]: list(solve(l)) == grp1(l)
Out[36]: True

相关问题 更多 >