返回

数组去重的神奇技巧:不止set()与filter(),还有10种花样去重法!

前端

数组去重,在编程中可谓是家常便饭。无论是面试还是日常业务,你都能轻而易举地碰到它的身影。初学者往往对数组去重不屑一顾,自以为只需套用一下嵌套循环,分分钟搞定,殊不知这种方法不但费时费力,而且十分低效。

不要急,让我们从最基本的方法开始,逐个击破!

1. set()函数

set()函数可谓是去重的第一法宝,以其出色的性能和简洁的语法,在去重界独领风骚。

def remove_duplicates(lst):
    return set(lst)

lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出:{1, 2, 3, 4, 5}

set()函数的优点:

  • 性能优异,时间复杂度为O(n),空间复杂度为O(n);
  • 语法简洁明了,易于理解和使用;
  • 能够自动剔除重复元素,并保持元素的顺序不变。

set()函数的缺点:

  • 对于大量数据,set()函数可能需要消耗大量内存;
  • set()函数无法保持元素的原始类型,例如列表中的数字会被转换为整型。

2. filter()函数

filter()函数是另一个强大的去重工具,它允许我们根据指定的条件筛选元素。

def remove_duplicates(lst):
    return list(filter(lambda x: x not in seen, lst))

seen = set()
lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出: [4, 5]

filter()函数的优点:

  • 能够根据指定的条件进行过滤,灵活性强;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

filter()函数的缺点:

  • 语法相对复杂,对于初学者来说可能难以理解;
  • 性能不如set()函数优异。

3. 集合推导

集合推导是一种简洁的方式,它允许我们在一行代码中完成集合的创建和去重。

unique_lst = {x for x in lst if x not in seen}

集合推导的优点:

  • 代码简洁明了,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

集合推导的缺点:

  • 语法相对复杂,对于初学者来说可能难以理解;
  • 性能不如set()函数优异。

4. 列表推导

列表推导与集合推导类似,只不过它返回的是一个列表而不是集合。

unique_lst = [x for x in lst if x not in seen]

列表推导的优点:

  • 代码简洁明了,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

列表推导的缺点:

  • 语法相对复杂,对于初学者来说可能难以理解;
  • 性能不如set()函数优异。

5. 哈希表

哈希表是一种快速高效的数据结构,它能够在O(1)的时间复杂度内查找和插入元素。

def remove_duplicates(lst):
    hash_table = {}
    unique_lst = []
    for x in lst:
        if x not in hash_table:
            hash_table[x] = True
            unique_lst.append(x)
    return unique_lst

lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出: [4, 5]

哈希表的优点:

  • 查找和插入元素的时间复杂度为O(1);
  • 内存消耗较低,适用于大量数据的去重;
  • 能够保持元素的原始类型。

哈希表的缺点:

  • 代码相对复杂,对于初学者来说可能难以理解;
  • 哈希表不是内置的数据结构,需要额外的库或模块支持。

6. 字典

字典也是一种高效的数据结构,它能够在O(1)的时间复杂度内查找和插入元素。

def remove_duplicates(lst):
    unique_dict = {}
    for x in lst:
        unique_dict[x] = True
    return list(unique_dict.keys())

lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出: [4, 5]

字典的优点:

  • 查找和插入元素的时间复杂度为O(1);
  • 内存消耗较低,适用于大量数据的去重;
  • 能够保持元素的原始类型。

字典的缺点:

  • 代码相对复杂,对于初学者来说可能难以理解;
  • 字典不是内置的数据结构,需要额外的库或模块支持。

7. 计数器

计数器是一种简单有效的方法,它能够统计每个元素出现的次数。

def remove_duplicates(lst):
    counter = {}
    unique_lst = []
    for x in lst:
        if x not in counter:
            counter[x] = 0
        counter[x] += 1
    for x, count in counter.items():
        if count == 1:
            unique_lst.append(x)
    return unique_lst

lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出: [4, 5]

计数器的优点:

  • 代码简单易懂,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

计数器的缺点:

  • 对于大量数据,计数器可能需要消耗大量内存;
  • 性能不如set()函数和哈希表优异。

8. map()函数

map()函数允许我们对列表中的每个元素应用指定的函数。

def remove_duplicates(lst):
    unique_lst = list(map(lambda x: x, lst))
    return unique_lst

lst = [1, 2, 3, 4, 5, 1, 2, 3]
unique_lst = remove_duplicates(lst)
print(unique_lst)  # 输出: [1, 2, 3, 4, 5]

map()函数的优点:

  • 代码简洁明了,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

map()函数的缺点:

  • 语法相对复杂,对于初学者来说可能难以理解;
  • 性能不如set()函数和哈希表优异。

9. lambda表达式

lambda表达式允许我们在一行代码中定义一个匿名函数。

unique_lst = list(filter(lambda x: x not in seen, lst))

lambda表达式的优点:

  • 代码简洁明了,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较低,适用于大量数据的去重。

lambda表达式的缺点:

  • 语法相对复杂,对于初学者来说可能难以理解;
  • 性能不如set()函数和哈希表优异。

10. numpy

numpy是一个强大的科学计算库,它提供了许多高效的数组操作函数。

import numpy as np

unique_lst = np.unique(lst)

numpy的优点:

  • 代码简洁明了,易于理解和使用;
  • 能够保持元素的原始类型;
  • 内存消耗较