在Mathematica中,Max[]
是获取数字列表中最大数字的最有效函数,但是如何找到列表列表中包含最大最后一个元素的列表?例如在一系列坐标中具有最大x
部分的二维坐标。
我最好的尝试是SortBy
,但显然我不需要程序来排序我的列表,只需要我需要的最大值。
答案 0 :(得分:6)
也许:
list = {{4, 3}, {5, 10}, {-2, 1}, {3, 7}}
Reverse /@ Take[#, Ordering[#, -1]] &@(Reverse /@ #) &@ list
(*
-> {{5, 10}}
*)
利用Ordering[ ]
命令列出第一个元素
修改强>
或者更好(我认为):
Take[#, Ordering[Last /@ #, -1]] &@ list
修改强>
此外:
#[[Ordering[#, -1, Last@#2 > Last@#1 &]]] &@list
修改强>
也许更快:
#[[First@Position[#, Max@#] &@(Last /@ #)]] &@list
答案 1 :(得分:4)
以下是使用Pick
maxBy[list_, n_] := With[{s = list[[All, n]]}, Pick[list, s, Max[s]]]
maxBy[{{4, 3}, {5, 10}, {-2, 1}, {3, 7}}, 2]
(* output:
{{5, 10}}
*)
此版本适用于每个子列表中的任意数量的元素,n
小于或等于最短子列表的长度。
我机器上此版本的计时
list2 = RandomInteger[{-10^7, 10^7}, {10^6, 2}];
list3 = RandomInteger[{-10^7, 10^7}, {10^6, 3}];
list9 = RandomInteger[{-10^7, 10^7}, {10^6, 9}];
maxBy[list2, 2]; // Timing
maxBy[list3, 2]; // Timing
maxBy[list9, 2]; // Timing
(* output:
{0.030341, Null}
{0.030912, Null}
{0.033313, Null}
*)
与David的代码相比
maxBy[list2, 2]; // Timing
maxBy[list3, 2]; // Timing
maxBy[list9, 2]; // Timing
(* ouput:
{0.186175, Null}
{0.184989, Null}
{0.262018, Null}
*)
maxBy[list2, 2]; // Timing
maxBy[list3, 2]; // Timing
maxBy[list9, 2]; // Timing
(* ouput:
{0.944016, Null}
{0.83094, Null}
{0.874126, Null}
*)
和belisarius'代码
Reverse /@ Take[#, Ordering[#, -1]] &@(Reverse /@ #) &@list2; // Timing
Take[#, Ordering[Last /@ #, -1]] &@list2; // Timing
#[[Ordering[#, -1, Last@#2 > Last@#1 &]]] &@list2; // Timing
#[[First@Position[#, Max@#] &@(Last /@ #)]] &@list2; // Timing
(* output:
{0.211016, Null}
{0.099253, Null}
{2.03415, Null}
{0.266934, Null}
*)
答案 2 :(得分:1)
这个函数怎么样(这里仅为2D列表定义):
maxBy = Module[{pattern = Reverse@Insert[{Max@#1[[All, #2]]}, _, #2]},
Cases[#1, pattern]] &
list = {{4, 3}, {5, 10}, {20, 1}, {3, 7}};
maxBy[list, 1]
Out[1]= {{20, 1}}
maxBy[list, 2]
Out[2]= {{5, 10}}
答案 3 :(得分:1)
这是一种依赖于Transpose
的方法:
maxBy = #1[[Position[t = Transpose[#1][[#2]], Max[t]][[All, 1]]]] &;
例如: list = {{4,3},{5,10},{20,1},{3,7}};
maxBy[list, 1]
(* {{20, 1}} *)
maxBy[list, 2]
(* {{5, 10}} *)
每个子列表可以处理两个以上的元素,前提是这些子列表的长度都相同。
r:=RandomInteger[{-10^5,10^5}];
list3=Table[{r,r,r},{j,10^2}]; (* 3 numbers in each sublist *)
list9=Table[{r,r,r,r,r,r,r,r,r},{j,10^2}]; (* 9 numbers *)
maxBy[list3, 2] (* Find max in position 2 of list3 *)
(* {{-93332, 99582, 4324}} *)
maxBy[list9, 5] (* Find max in position 5 of list9 *)
(* {{7680, 85508, 51915, -58282, 94679, 50968, -12664, 75246, -82903}} *)
当然,结果会根据您生成的随机数而有所不同。
修改强>
这是大型列表的一些时序数据。 SortBy
明显变慢了。但似乎并不受每个子列表中元素数量的影响。首先,我的maxBy
代码后跟SortBy
:
使用相同的list2,这是Yoda代码的一些时序数据。虽然他的例程也被称为maxBy,但是他产生了以下输出:
同样,使用相同的list2,Belisarius代码的一些数据:
他的第二个建议是所有测试中最快的。
答案 4 :(得分:1)
不是最有效但更简单的吗?
max = Max@list[[All, -1]];
Cases[list, {_, max}]
或
max = Max@list3[[All, -1]];
Cases[list3, {_,_, max}]
<强>用法强>
list = {{40, 3}, {5, 10}, {-2, 1}, {3, 10}}
max = Max@list[[All, -1]];
Cases[list, {_, max}]
输出:
{{5, 10}, {3, 10}}
答案 5 :(得分:1)
在阅读了一些文档并做了一些实验后,我设法更清楚地了解了这个问题。
我实际上想知道为什么Max[]
似乎故意避免提供指令,使其不仅返回max元素本身,还返回其位置。毕竟,提供位置不会改变算法的O(n)复杂度。例如,想象一下:
In[1]:= Max[{991, 993, 992}, ReturnPosition -> True]
Out[1]= {2}
如果可以,您可以使用下面的代码来解决我的问题:
list[[Max[list[[All, -1]], ReturnPosition -> True]]]
但是现在我意识到系统函数Max[]
是而不是设计用于查找列表中的max元素。你可以看出,Wolfram团队显然使Max[]
更像是数学中的传统max
函数 - 它做了简单的符号简化,它自动展平了所有列表,它可以在一个可绘制的函数中,并且大多数重要的是,它是Orderless
:
In[2]:= Attributes[Max]
Out[2]= {Flat, NumericFunction, OneIdentity, Orderless, Protected}
这使得职位毫无意义。总之,它将内部的所有列表视为数学集。
因此,哲学上Mathematica计算它并非易事。我需要做的就是“DIY”一个具有O(n)复杂性的功能,并且可以完成这项工作。我认为TomD正朝着正确的方向前进,尽管我更喜欢:
maxLast[l_] := Cases[l, {___, Max[Last/@l]}]
和Heike(黑客?)采用Pick
可能有更好的技术专门用于选择元素,但算法的复杂性必须没有虚拟差异。我可以用这种方式重写它:(名字和头部越少,速度越快)
maxLast[l_] := Pick[l, #, Max[#]] &[Last /@ l]
他们都是很好的答案。