从列表中移除重复元素,但仅限于奇数个重复的元素

2 投票
3 回答
727 浏览
提问于 2025-04-28 09:34

我想从一个列表中去掉那些出现次数是奇数的重复元素。举个例子,对于这个列表:[1, 2, 3, 3, 3, 5, 8, 1, 8],数字1出现了2次,数字3出现了3次,数字8也出现了2次。所以1和8应该被去掉,而数字3只保留1个。

这是我想到的解决方法:

def remove_odd_duplicates(arr):
    h = {}
    for i in arr:
        if i in h:
            h[i] += 1
        else:
            h[i] = 1

    arr = []
    for i in h:
        if h[i] % 2:
            arr.append(i)

    return arr

这个方法返回的结果是正确的:[2, 3, 5],但我觉得可以用更好的方式来写。有没有什么好的建议呢?

暂无标签

3 个回答

1

你可以试试用 scipy.stats.itemfreq 这个工具:

>>> from scipy.stats import itemfreq
>>> xs = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> ifreq = itemfreq(xs)
>>> ifreq
array([[1, 2],
       [2, 1],
       [3, 3],
       [5, 1],
       [8, 2]])
>>> i = ifreq[:, 1] % 2 != 0
>>> ifreq[i, 0]
array([2, 3, 5])
2

如果顺序不重要:

>>> a = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> list(set([x for x in a if a.count(x)%2 == 1]))
[2, 3, 5]

这个列表推导式 [x for x in a if a.count(x)%2 == 1] 只会返回那些在列表中出现奇数次的元素。list(set(...)) 是一种常见的方法,用来去掉列表中的重复项。

4

你可以使用 collections.Counter 和列表推导式,像这样:

data = [1, 2, 3, 3, 3, 5, 8, 1, 8]
from collections import Counter
print [item for item, count in Counter(data).items() if count % 2]
# [2, 3, 5]

Counter 会生成一个字典,字典里的每个元素都是你输入的可迭代对象中的键,而它们对应的值就是出现的次数。所以,我们遍历这个字典,检查每个元素的出现次数是否是奇数,然后只保留那些奇数的元素。

注意:这个方法的复杂度还是 O(N),和你最开始的程序是一样的。

撰写回答