5 回答
TA贡献1784条经验 获得超2个赞
您可以使用计数器
>>> from collections import Counter
>>> l = [2, 3, 6, 6, 8, 9, 12, 12, 14]
>>> res = [el for el, cnt in Counter(l).items() if cnt==1]
>>> res
[2, 3, 8, 9, 14]
TA贡献1831条经验 获得超10个赞
您始终可以拥有两套。一个用于检查是否seen,另一个仅用于保持唯一。set.discard(el)如果存在将删除。
Inputlist = [2, 3, 6, 6, 8, 9, 12, 12, 14]
seen = set()
ans = set()
for el in Inputlist:
if el not in seen:
seen.add(el)
ans.add(el)
else:
ans.discard(el)
print(list(ans))
编辑:为了咯咯笑,我测量了这两种解决方案的性能
from timeit import timeit
first = """
def get_from_two_sets():
seen = set()
ans = set()
for el in (2, 3, 6, 6, 8, 9, 12, 12, 14):
if el not in seen:
seen.add(el)
ans.add(el)
else:
ans.discard(el)"""
second = """
def get_from_counter():
return [el for el, cnt in Counter((2, 3, 6, 6, 8, 9, 12, 12, 14)).items() if cnt == 1]
"""
print(timeit(stmt=first, number=10000000))
print(timeit(stmt=second, number=10000000, setup="from collections import Counter"))
产量
0.3130729760000577
0.46127468299982866
太棒了!看来我的解决方案稍微快一些。不要浪费你节省的纳秒!
@abc 解决方案很干净并且Pythonic,那就去做吧。
TA贡献1851条经验 获得超3个赞
一个简单的列表理解就可以解决问题:
Inputlist = [2, 3, 6, 6, 8, 9, 12, 12, 14]
Outputlist = [item for item in Inputlist if Inputlist.count(item) == 1]
TA贡献1876条经验 获得超5个赞
使用集合的另一种解决方案:将输入列表转换为集合,并从输入列表中删除该集合的所有元素。这只会在列表中留下重复项。现在将其转换为一组,您可以从一组中减去另一组。听起来很复杂,但对于短列表来说相当简短且高效:
l = [2, 3, 6, 6, 8, 9, 12, 12, 14]
inset = set(l)
for i in inset: # <-- usually the element to remove is in the front,
l.remove(i) # <-- but in a worst case, this is slower than O(n)
result = list(inset - set(l))
与简短示例列表无关的性能:
# %timeit this solution
1.18 µs ± 1.97 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# %timeit solution with seen-set
1.23 µs ± 1.49 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# %timeit solution with Counter class
2.76 µs ± 4.85 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
对于包含 1000 个元素和 10% 重复项的列表,计数器解决方案是最快的!
TA贡献2012条经验 获得超12个赞
对于仅应删除连续重复项的情况的替代解决方案:
from itertools import groupby
inputlist = [2, 3, 6, 6, 8, 9, 12, 12, 14]
outputlist = [x for _, (x, *extra) in groupby(inputlist) if not extra]
这一切所做的就是将相同值的运行组合在一起,将第一个副本解压到x,其余的输入list; 我们检查 said 是否list为空,以确定是否只有一个值,还是多个值,并且只保留单个值的值。
如果您甚至不喜欢临时的,使用不验证组的解决方案之一将允许类似的解决方案,但没有无限制的临时存储extra
list
:ilen
list
outputlist = [x for x, grp in groupby(inputlist) if ilen(grp) == 1]
或者使用一个仅检查“至少 2”而不迭代超出该点的助手:
def more_than_one(it):
next(it) # Assumes at least once, which is already the case with groupby groups
try:
next(it)
except StopIteration:
return True
return False
outputlist = [x for x, grp in groupby(inputlist) if not more_than_one(grp)]
注意:一般来说,我实际上更喜欢基于abc 的Counter
解决方案,但如果您实际上只想删除相邻的重复项,那么它不足以完成任务。
添加回答
举报