查找最大或最小的 N 个元素
问题
获得一个列表(列表元素很多)中最大或者最小的 N 个元素列表?
实现
当要查找的元素个数 N 相对比较小的时候
1
2
3
4
5
6
7
8
9
10
11>>> import heapq
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
# 取最大的 3 个数
>>> heapq.nlargest(3, nums)
[42, 37, 23]
# 取最小的 3 个数
>>> heapq.nsmallest(3, nums)
[-4, 1, 2]当要查找的元素个数 N 接近要查找的可迭代对象的长度时,出于性能考虑,可用切片替代
1
2
3
4
5
6
7
8
9>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
# 取最大的 3 个数
>>> sorted(nums, reverse=True)[:3]
[42, 37, 23]
# 取最小的 3 个数
>>> sorted(nums)[:3]
[-4, 1, 2]当取一个最大值或最小值,通过
max
和min
函数获得1
2
3
4
5
6
7
8
9>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
# 取最大数
>>> max(nums)
42
# 取最小数
>>> min(nums)
-4测试示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47>>> import heapq
>>> import timeit
>>> import random
>>> nums = random.choices(range(50000), k=20000)
>>> len(nums)
20000
# ---------------------------------------------------------------------------------
# 从nums中取10个最小的数
# 通过 sorted(nums)[:10] 方式
>>> timeit.repeat('sorted(nums)[:10]', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[5.283976222000092, 5.281303266000577, 5.272159137000017] # 执行1000遍,重复3次用时列表
# 通过heapq.nsmallest(10, nums) 方式
>>> timeit.repeat('heapq.nsmallest(10, nums)', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[1.1154322049997063, 1.065238846000284, 1.0126771430004737] # 执行1000遍,重复3次用时列表
# ---------------------------------------------------------------------------------
# 从nums中取10个最大的数
# 通过 sorted(nums)[:10] 方式
>>> timeit.repeat('sorted(nums, reverse=True)[:10]', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[5.402307174000271, 5.62465228200017, 5.546984251999675]
# 通过 heapq.nlargest(10, nums) 方式
>>> timeit.repeat('heapq.nlargest(10, nums)', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[1.0458967599997777, 1.060633938999672, 1.0392043130004822] # 执行1000遍,重复3次用时列表
# ---------------------------------------------------------------------------------
# 从nums中取10000个最小的数
# 通过 sorted(nums)[:10000] 方式
>>> timeit.repeat('sorted(nums)[:10000]', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[5.616329210999538, 5.384628143000555, 5.36661329799972] # 执行1000遍,重复3次用时列表
# 通过heapq.nsmallest(10000, nums) 方式
>>> timeit.repeat('heapq.nsmallest(10000, nums)', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[30.37623528200038, 30.471836461999374, 30.748560685000484] # 执行1000遍,重复3次用时列表
# ---------------------------------------------------------------------------------
# 从nums中取10000个最大的数
# 通过 sorted(nums, reverse=True)[:10000] 方式
>>> timeit.repeat('sorted(nums, reverse=True)[:10000]', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[5.462146738999763, 5.569061694000084, 5.482768033999491] # 执行1000遍,重复3次用时列表
# 通过 heapq.nlargest(10000, nums) 方式
>>> timeit.repeat('heapq.nlargest(10000, nums)', 'import heapq;from __main__ import nums', number=1000, repeat=3)
[33.05006609500015, 30.762279339999623, 33.79276524299985] # 执行1000遍,重复3次用时列表