\begingroup
如何从以下列表中有效地选择具有第三个元素最小值的子列表?
longList = {{1, 1, 12}, {1, 2, 10}, {1, 3, 12}, {1, 4, 12}, {1, 5, 10},
{2, 1, 10}, {2, 2, 8}, {2, 3, 10}, {2, 4, 10}, {2, 5, 8},
{3, 1, 12}, {3, 2, 10}, {3, 3, 12}, {3, 4, 12}, {3, 5, 10}};
Select[longList, #[[3]] == Min[longList[[All, 3]]] &]
假设所有数字都是整数,并且这个数字longList
相当大,包含大约 1 亿个元素。
\endgroup
6 个回答
6
\begingroup
随机数据
longList = RandomInteger[100, {1000,5}];
您的解决方案
AbsoluteTiming[
Select[longList, #[[3]] == Min[longList[[All, 3]]] &]
]
(* {0.017431,{{100,81,0,36,91},{6,33,0,76,0},{9,9,0,19,16},{56,81,0,16,10},{72,31,0,9,3},{34,97,0,38,79},{53,93,0,32,37},{98,94,0,84,60}}}*)
我的解决方案
部分、位置
AbsoluteTiming[
Part[#, Flatten@ Position[#[[All, 3]], Min[#[[All, 3]]]]]& @ longList
]
(* {0.000173,{{100,81,0,36,91},{6,33,0,76,0},{9,9,0,19,16},{56,81,0,16,10},{72,31,0,9,3},{34,97,0,38,79},{53,93,0,32,37},{98,94,0,84,60}}} *)
最小值,提取
MinimalBy[Extract[3]]@ longList
基准
theTrends =Transpose@Table[
With[
{longList = RandomInteger[100, {k,5}]},
{
{k, First@AbsoluteTiming@Select[longList, #[[3]] == Min[longList[[All, 3]]] &]}, (* OP *)
{k, First@AbsoluteTiming[Part[#, Flatten@ Position[#[[All, 3]], Min[#[[All, 3]]]]]& @ longList]}, (* rhermans *)
{k, First@AbsoluteTiming@MinimalBy[Extract[3]]@ longList}, (* rhermans *)
{k, First@AbsoluteTiming@Pick[longList, longList[[All, 3]], Min[longList[[All, 3]]]]}, (* "user1066" *)
{k, First@AbsoluteTiming[MinimalBy[longList, #[[3]] &]@longList]} (* PlatoManiac *)
}
]
,{k, PowerRange[2, 2^17, 2]}
];
\endgroup
1
-
\begingroup
我也刚刚尝试了这种方法user1066
,它似乎可以更快地处理大型列表。
\endgroup
–
|
\begingroup
With[{x = longList[[All, 3]]}, Pick[longList, x, Min[x]]]
(* {{4, 29, 0, 15, 40}, {31, 3, 0, 3, 61}, {86, 12, 0, 13, 54},
{48, 56, 0, 4, 94}, {19, 94, 0, 56, 28}, {90, 57, 0, 91,51},
{76, 14, 0, 70, 84}} *)
原始答案
Pick[longList, longList[[All, 3]],
Min[longList[[All, 3]]]] // AbsoluteTiming
(* {0.000064, {{4, 29, 0, 15, 40}, {31, 3, 0, 3, 61}, {86, 12, 0, 13,
54}, {48, 56, 0, 4, 94}, {19, 94, 0, 56, 28}, {90, 57, 0, 91,
51}, {76, 14, 0, 70, 84}}} *)
使用longlist
由@rhermans 定义
longList = RandomInteger[100, {1000,5}];
和
Select[longList, #[[3]] == Min[longList[[All, 3]]] &] ==
Pick[longList, longList[[All, 3]], Min[longList[[All, 3]]]]
(* True *)
\endgroup
1
-
\begingroup
在我的计算机上,这稍微快一些:With[{x = longList . {0, 0, 1, 0, 0}}, Pick[longList, x, Min[x]]]
\endgroup
–
|
\begingroup
您的解决方案还不错,但问题在于Min[longList[[All, 3]]]
对 longList 中的每个元素都重复进行评估。计算一次最小值:
longList = {{1, 1, 12}, {1, 2, 10}, {1, 3, 12}, {1, 4, 12}, {1, 5,
10}, {2, 1, 10}, {2, 2, 8}, {2, 3, 10}, {2, 4, 10}, {2, 5, 8}, {3,
1, 12}, {3, 2, 10}, {3, 3, 12}, {3, 4, 12}, {3, 5, 10}};
min = Min[longList[[All, 3]]];
Select[longList, #[[3]] == min &] // AbsoluteTiming
{0.0000158, {{2, 2, 8}, {2, 5, 8}}}
\endgroup
1
-
\begingroup
很好,我运行了 45 多分钟然后就停了下来,因为它太慢了。
\endgroup
–
|
\begingroup
对于大型列表,这也应该可以相当快地工作。
longList = RandomInteger[100, {100000000, 5}];
MinimalBy[longList, #[[3]] &]; // AbsoluteTiming
{5.28234, 空}
\endgroup
|
\begingroup
抓取@rhermans 定义的长名单:
longList = RandomInteger[100, {1000,5}];
使用PositionSmallest
和Extract
:
Extract[longList, Outer[List, PositionSmallest[longList[[All, 3]]]]] ==
Pick[longList, longList[[All, 3]], Min[longList[[All, 3]]]]
(*True*)
\endgroup
0
|
\begingroup
使用Reap
、Sow
和Scan
:
Reap[Scan[If[#[[3]] == Min[longList[[All, 3]]], Sow[#]] &,
longList]][[2, 1]]
\endgroup
|
|