You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python移除列表重复元素且保留首尾实例的更Pythonic实现方式

移除列表重复元素(仅保留目标元素首尾实例)的Pythonic实现

原有实现的潜在问题

你提供的两种写法都存在索引偏移的隐患:

  • 第一种实现正向遍历删除索引时,删除靠前的元素后,后续元素的索引会整体前移,当目标重复次数≥3时会出现删错甚至IndexError的问题
  • 第二种实现遍历切片lst[1:-1]时,切片是原列表的浅拷贝快照,删除原列表元素后遍历逻辑会漏判后续元素,相邻重复场景下会失效

更Pythonic的实现方案

推荐直接构建新列表的方式,时间复杂度O(n),没有索引偏移问题,可读性也更高:

场景1:仅针对单个指定目标元素过滤

lst = ["foo", "bar", "foobar", "foo", "barfoo", "foo"]
target = "foo"

# 取目标元素第一次和最后一次出现的索引
first_idx = lst.index(target)
last_idx = len(lst) - 1 - lst[::-1].index(target)

# 生成过滤后的新列表
res = [
    val for idx, val in enumerate(lst)
    if idx in (first_idx, last_idx) or val != target
]
print(res) # 输出:['foo', 'bar', 'foobar', 'barfoo', 'foo']

场景2:对列表中所有元素都执行「保留首尾、删除中间重复」

如果需要处理所有元素的重复,而非单个目标,可以用collections.defaultdict记录每个元素的出现位置再过滤:

from collections import defaultdict

lst = ["foo", "bar", "foo", "bar", "foobar", "bar"]
pos_map = defaultdict(list)

# 记录每个元素所有出现的索引
for idx, val in enumerate(lst):
    pos_map[val].append(idx)

# 生成白名单索引:所有元素的首尾出现位置
keep_idx = set()
for positions in pos_map.values():
    keep_idx.add(positions[0])
    keep_idx.add(positions[-1])

res = [val for idx, val in enumerate(lst) if idx in keep_idx]
print(res) # 输出:['foo', 'bar', 'foobar', 'bar']

原实现修复方案

如果你一定要在原列表上执行删除操作,需要倒序遍历要删除的索引,避免索引偏移:

lst = ["foo", "bar", "foobar", "foo", "barfoo", "foo"]
occurence = [i for i, e in enumerate(lst) if e == "foo"]
to_remove = occurence[1:-1]
# 倒序删除就不会出现索引错位问题
for i in reversed(to_remove):
    del lst[i]
print(lst) # 输出:['foo', 'bar', 'foobar', 'barfoo', 'foo']

内容的提问来源于stack exchange,提问作者o.sk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 04:06:00