求解数组中的最小的几个值索引方法
求解数组中的最小的几个值索引方法
这其中分为普通列表和np数组的区别
普通的列表
方法一、使用 sorted排序
sorted和sort的区别:sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
语法:
sorted(iterable, cmp=None, key=None, reverse=False)
参数说明:
- iterable -- 可迭代对象。
- cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
- key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值:返回重新排序的列表。
实例:
>>>a = [5,7,6,3,4,1,2]
>>> b = sorted(a) # 保留原列表
>>> a
[5, 7, 6, 3, 4, 1, 2]
>>> b
[1, 2, 3, 4, 5, 6, 7]
>>> L=[('b',2),('a',1),('c',3),('d',4)]
>>> sorted(L, cmp=lambda x,y:cmp(x[1],y[1])) # 利用cmp函数
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> sorted(L, key=lambda x:x[1]) # 利用key
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年龄排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(students, key=lambda s: s[2], reverse=True) # 按降序
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>>
排序实例
arr = [4, 1, 3, 1, 5]
k = 2 # 取最小的2个值的索引
# 生成索引列表并按值排序
sorted_indices = sorted(range(len(arr)), key=lambda i: arr[i])[:k]
print(sorted_indices) # 输出 [1, 3]
方法二、使用 heapq.nsmallest 高效获取
在Python中,heapq模块提供了一个非常有用的函数nsmallest,它允许我们快速找到一个集合中最小的N个元素。这个函数特别适合于当我们需要从一个较大的集合中找到一些最小元素,但又不想对整个集合进行排序时使用。
基本用法:
heapq.nsmallest函数的基本用法非常简单。你只需要提供两个参数:一个是你想要找到的元素的数量N,另一个是你的数据集合。
例如,如果你有一个数字列表并且想要找到其中最小的三个数:
import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nsmallest(3, nums)) # 输出: [-4, 1, 2]
使用关键字参数
nsmallest函数也接受一个关键字参数key,这使得它可以在更复杂的数据结构中使用。key参数接受一个函数,这个函数用于从你的数据元素中提取一个用于比较的关键字。
例如,如果你有一个包含多个字段的字典列表,并且想要根据其中的price字段来找到最小的三个元素
portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
print(cheap)
# 输出: [{'name': 'YHOO', 'shares': 45, 'price': 16.35},
# {'name': 'FB', 'shares': 200, 'price': 21.09},
# {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
当N的值相对较小,特别是远小于集合的大小时,使用nsmallest函数比排序整个集合然后取前N个元素要高效得多。这是因为heapq模块的函数在底层使用了堆数据结构来优化这些操作。然而,如果N的值接近集合的大小,那么使用常规的排序可能会更快。此外,如果你只是想找到单个的最小或最大元素(N=1),那么使用内置的min()和max()函数会更加快速。
排序实例
import heapq
arr = [4, 1, 3, 1, 5]
k = 2
# 直接获取前k小值的索引
heapq_indices = heapq.nsmallest(k, range(len(arr)), key=lambda i: arr[i])
print(heapq_indices) # 输出 [1, 3]
Numpy数组
方法一、使用 np.argsort 排序
在Python中,np.argsort函数是NumPy库中的一个重要功能,它用于返回输入数组(array)按升序排序后的索引数组。这个函数不返回排序后的数组,而是返回从原始数组中提取元素后,这些元素将会按照升序排列的新数组的索引。
基本用法:
np.argsort的参数
np.argsort函数接受以下参数:
- a:要排序的数组。
- axis:指定沿着哪个轴进行排序,默认是-1,表示对最后一个轴进行排序。
- kind:排序算法的选择,可以是'quicksort'、'mergesort'或'heapsort',默认是'quicksort'。
- order:如果a是结构体数组,该参数指定按哪个字段进行排序。
实例:
import numpy as np
# 创建一个简单的数组
arr = np.array([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5])
# 使用np.argsort()获取排序后的索引
sorted_indices = np.argsort(arr)
print("原始数组:", arr)
print("排序后的索引:", sorted_indices)
输出结果将会是:
原始数组: [3 1 4 1 5 9 2 6 5 3 5]
排序后的索引: [1 3 6 0 9 2 4 8 10 7 5]
二维数组实例:
# 创建一个二维数组
arr_2d = np.array([[3, 2, 1], [9, 7, 5], [8, 6, 4]])
# 对二维数组的第一轴(行)进行排序
sorted_indices_axis0 = np.argsort(arr_2d, axis=0)
# 对二维数组的第二轴(列)进行排序
sorted_indices_axis1 = np.argsort(arr_2d, axis=1)
print("按行排序后的索引:", sorted_indices_axis0)
print("按列排序后的索引:", sorted_indices_axis1)
排序实例
import numpy as np
arr = np.array([4, 1, 3, 1, 5])
k = 2
# 完全排序后取前k个索引
indices = np.argsort(arr)[:k]
print(indices) # 输出 [1 3]
方法二、使用 np.argpartition 高效分片(适合大数组)
NumPy的argpartition函数是一个非常有用的工具,它可以快速找到数组中第k个最大元素的索引,并且能够将数组重新排列,使得任何一个给定的元素(通过索引指定)都会被放置在一个排序后的数组中正确的位置上。这个函数不会改变原始数组,而是返回一个新的索引数组。
基本用法:
argpartition函数的参数包括:
- a:输入的NumPy数组。
- kth:指定的元素索引,可以是一个整数或一个整数序列。如果是一个整数,函数会找到这个索引对应的元素,并将其放置在排序后的数组中正确的位置上。如果是一个整数序列,函数会同时处理所有指定的索引。
- axis:沿着哪个轴进行操作,默认是-1,即最后一个轴。
- kind:选择算法,默认是'introselect'。
- order:如果数组有字段定义,这个参数指定哪些字段先比较,哪些字段后比较。
实例:
import numpy as np
# 创建一个NumPy数组
arr = np.array([3, 9, 1, 0, 2, 1, 7, 5])
# 使用argpartition找到最大的三个元素的索引
k = 3
indices = np.argpartition(arr, -k)[-k:]
# 使用索引获取这些元素
top_k_elements = arr[indices]
在这个例子中,argpartition函数将数组arr分成两部分,索引-k之前的所有元素都小于第k大的元素,而索引-k之后的所有元素都大于或等于第k大的元素。然后,通过选择最后k个元素的索引,我们可以得到最大的k个元素。
排序实例
import numpy as np
arr = np.array([4, 1, 3, 1, 5])
k = 2
# 分区获取前k小值索引(可能无序)
indices = np.argpartition(arr, k)[:k]
# 对结果再排序以保持升序
sorted_indices = indices[np.argsort(arr[indices])]
print(sorted_indices) # 输出 [1 3]
性能对比
性能对比:
- 对小数组,
sorted或np.argsort简单直接。 - 对大型数组,
heapq.nsmallest或np.argpartition更高效。

浙公网安备 33010602011771号