为了账号安全,请及时绑定邮箱和手机立即绑定

如何删除列表中重复数字的所有实例?

如何删除列表中重复数字的所有实例?

一只名叫tom的猫 2023-08-22 16:07:18
我想要一个代码来删除列表中重复的任何数字的所有实例。例如:Inputlist = [2, 3, 6, 6, 8, 9, 12, 12, 14] Outputlist = [2,3,8,9,14]我已经尝试删除列表中的重复元素(通过使用“unique”函数),但它仍然在列表中留下该元素的单个实例!seen = set()uniq = []for x in Outputlist:    if x not in seen:        uniq.append(x)        seen.add(x)      seen我也浏览了很多 StackOverflow 文章,但所有文章的想法都不同,即他们正在搜索从两个不同列表中删除公共元素,或者他们只想保留每个元素的一个实例。我想简单地删除所有常见元素。
查看完整描述

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]


查看完整回答
反对 回复 2023-08-22
?
慕哥6287543

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,那就去做吧。


查看完整回答
反对 回复 2023-08-22
?
皈依舞

TA贡献1851条经验 获得超3个赞

一个简单的列表理解就可以解决问题:


Inputlist = [2, 3, 6, 6, 8, 9, 12, 12, 14]

 

Outputlist = [item for item in Inputlist if Inputlist.count(item) == 1]


查看完整回答
反对 回复 2023-08-22
?
慕运维8079593

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% 重复项的列表,计数器解决方案是最快的!


查看完整回答
反对 回复 2023-08-22
?
繁花如伊

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 listilenlist


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解决方案,但如果您实际上只想删除相邻的重复项,那么它不足以完成任务。



查看完整回答
反对 回复 2023-08-22
  • 5 回答
  • 0 关注
  • 1648 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信