获取二维数组中每列的第二个最小值
Posted
技术标签:
【中文标题】获取二维数组中每列的第二个最小值【英文标题】:Get second minimum values per column in 2D array 【发布时间】:2020-06-23 10:21:11 【问题描述】:如何从每列中获取第二个最小值?我有这个数组:
A = [[72 76 44 62 81 31]
[54 36 82 71 40 45]
[63 59 84 36 34 51]
[58 53 59 22 77 64]
[35 77 60 76 57 44]]
我希望有这样的输出:
A = [54 53 59 36 40 44]
【问题讨论】:
第二个最小值每列? 【参考方案1】:试试这个,只需一行:
[sorted(i)[1] for i in zip(*A)]
在行动:
In [12]: A = [[72, 76, 44, 62, 81, 31],
...: [54 ,36 ,82 ,71 ,40, 45],
...: [63 ,59, 84, 36, 34 ,51],
...: [58, 53, 59, 22, 77 ,64],
...: [35 ,77, 60, 76, 57, 44]]
In [18]: [sorted(i)[1] for i in zip(*A)]
Out[18]: [54, 53, 59, 36, 40, 44]
zip(*A)
将转置您的列表列表,使列变为行。
如果你有重复的值,例如:
In [19]: A = [[72, 76, 44, 62, 81, 31],
...: [54 ,36 ,82 ,71 ,40, 45],
...: [63 ,59, 84, 36, 34 ,51],
...: [35, 53, 59, 22, 77 ,64], # 35
...: [35 ,77, 50, 76, 57, 44],] # 35
如果需要同时跳过35
s,可以使用set()
:
In [29]: [sorted(list(set(i)))[1] for i in zip(*A)]
Out[29]: [54, 53, 50, 36, 40, 44]
【讨论】:
【参考方案2】:numpy
数组的操作应该用numpy
函数完成,所以看看这个:
np.sort(A, axis=0)[1, :]
Out[61]: array([54, 53, 59, 36, 40, 44])
【讨论】:
据我所知,这必须是最好的解决方案,它将所有内容保存在numpy
中,我认为lambda
必须放慢heapq.nsmallest
解决方案。似乎最好在 numpy
中保持一切快速【参考方案3】:
你可以使用heapq.nsmallest
from heapq import nsmallest
[nsmallest(2, e)[-1] for e in zip(*A)]
输出:
[54, 53, 50, 36, 40, 44]
我添加了一个简单的基准来比较已发布的不同解决方案的性能:
from simple_benchmark import BenchmarkBuilder
from heapq import nsmallest
b = BenchmarkBuilder()
@b.add_function()
def MehrdadPedramfar(A):
return [sorted(i)[1] for i in zip(*A)]
@b.add_function()
def NicolasGervais(A):
return np.sort(A, axis=0)[1, :]
@b.add_function()
def imcrazeegamerr(A):
rotated = zip(*A[::-1])
result = []
for arr in rotated:
# sort each 1d array from min to max
arr = sorted(list(arr))
# add the second minimum value to result array
result.append(arr[1])
return result
@b.add_function()
def Daweo(A):
return np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)
@b.add_function()
def kederrac(A):
return [nsmallest(2, e)[-1] for e in zip(*A)]
@b.add_arguments('Number of row/cols (A is square matrix)')
def argument_provider():
for exp in range(2, 18):
size = 2**exp
yield size, [[randint(0, 1000) for _ in range(size)] for _ in range(size)]
r = b.run()
r.plot()
将zip
与sorted
函数结合使用是小型二维列表的最快解决方案,而将zip
与heapq.nsmallest
结合使用则在大型二维列表中表现最佳
【讨论】:
只是一个疯狂的想法:这些结果会受到您生成的数字不是 numpy dtypes 的影响吗?另外,内置的 randint 不会返回列表而不是数组吗? 这是迭代 np.matrix 上的行的唯一方法吗?有更快的替代方案吗?【参考方案4】:我希望我正确理解了您的问题,但无论哪种方式,这都是我的解决方案,我确信有一种更优雅的方式可以做到这一点,但它确实有效
A = [[72,76,44,62,81,31]
,[54,36,82,71,40,45]
,[63,59,84,36,34,51]
,[58,53,59,22,77,64]
,[35,77,50,76,57,44]]
#rotate the array 90deg
rotated = zip(*A[::-1])
result = []
for arr in rotated:
# sort each 1d array from min to max
arr = sorted(list(arr))
# add the second minimum value to result array
result.append(arr[1])
print(result)
【讨论】:
【参考方案5】:假设A
是numpy.array
(如果这成立,请考虑在您的问题中添加numpy
标签)然后您可以使用apply_along_axis
进行以下方式:
import heap
import numpy as np
A = np.array([[72, 76, 44, 62, 81, 31],
[54, 36, 82, 71, 40, 45],
[63, 59, 84, 36, 34, 51],
[58, 53, 59, 22, 77, 64],
[35, 77, 60, 76, 57, 44]])
second_mins = np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)
print(second_mins) # [54 53 59 36 40 44]
请注意,我使用了 heapq.nsmallest,因为它会根据需要进行尽可能多的排序以获得 2 个最小元素,而 sorted
会完成排序。
【讨论】:
【参考方案6】:>>> A = np.arange(30).reshape(5,6).tolist()
>>> A
[[0, 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]]
更新:
使用set
防止使用zip(*A)
重复和转置列表
>>> [sorted(set(items))[1] for items in zip(*A)]
[6, 7, 8, 9, 10, 11]
old:每行中的第二个最小项目
>>> [sorted(set(items))[1] for items in A]
[1, 7, 13, 19, 25]
【讨论】:
这不是在每一行而不是列中获取第二项吗?以上是关于获取二维数组中每列的第二个最小值的主要内容,如果未能解决你的问题,请参考以下文章
Java求解! 定义一个6行6列的二维整型数组,输出该二维数组中的每行和每列的最大值、最小值、和平均值。
计算机二级-C语言-程序设计题-190119记录-求出一个二维数组每一列的最小值。
C语言试题二十三之编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中
C语言试题二十三之编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中