我有以下数据对列表:
pairs = {{3, "John"}, {1, "Bob"}, {2, "Jane"}, {1, "Beth"}};
我想找到具有最小第一个值的数据对。在上面的示例中,我正在寻找的是:{1, "Bob"}
或{1, "Beth"}
,但不是两者。
我可以使用Sort[pairs, #1[[1]] < #2[[1]] &][[1]]
来完成此任务。然而,因为即使是具有大O>的最快种类也是如此。 O(n),它让我认为必须有一种更有效的方法来做到这一点。
以下给出了正确答案:
minPair = pairs[[1]];
Map[Function[x, If[x[[1]] < minPair[[1]], minPair = x]], pairs];
minPair;
但是,它比使用上面的Sort
要慢。我知道,我的Mathematica-fu还没有,所以我的问题。
SetAttributes[TimingDo, HoldRest];
TimingDo[note_String, func_] :=
results =
Append[results, {note , func, Timing[Do[func, {iterations}]][[1]]}];
pairs = {{3, "John"}, {1, "Bob "}, {2, "Jane"}, {1, "Beth"}};
results = {};
iterations = 10000;
TimingDo[ "mmorris[Sort]: ",
Sort[pairs, #1[[1]] < #2[[1]] &][[1]]];
TimingDo["mmorris[Map]: ",
minPair = pairs[[1]];
Map[Function[x, If[x[[1]] < minPair[[1]], minPair = x;]], pairs];
minPair];
TimingDo["mmorris[Map2]: ",
minPair = pairs[[1]];
minValue = minPair[[1]];
Map[Function[x,
If[x[[1]] < minValue, minPair = x; minValue = minPair[[1]];]],
pairs];
minPair];
TimingDo["Mike Honeychurch[Position]: ",
pairs[[Position[pairs, Min[pairs[[All, 1]]]][[1, 1]]]]];
TimingDo["Mike Honeychurch[Ordering]: ",
pairs[[First@Ordering[pairs[[All, 1]]]]]];
TimingDo["Mike Honeychurch[Ordering']: ",
pairs[[First@Ordering[pairs[[All, 1]], 1]]]];
TimingDo["Mike Honeychurch[SortBy]: ",
SortBy[pairs, First][[1]]];
cf = Compile[{{in, _Integer, 1}}, Block[{x, pos}, x = Part[in, 1];
pos = 0;
Do[If[Part[in, i] < x, x = Part[in, i];
pos = i;];, {i, Length[in]}];
pos]];
TimingDo["ruebenko[Compile]: ",
{p1, p2} = Developer`ToPackedArray /@ Transpose[pairs];
pairs[[cf[p1]]]];
TimingDo[ "ruebenko[Ordering]: ",
{p1, p2} = Developer`ToPackedArray /@ Transpose[pairs];
pairs[[Ordering[p1][[1]]]]];
TimingDo["TomD[Select]: ",
Select[pairs, #[[1]] == Min[pairs[[All, 1]]] &, 1][[1]]];
TimingDo["TomD[Function]: ",
(Function[xx, Select[xx, #[[1]] == Min[xx[[All, 1]]] &, 1]]@
pairs)[[1]]];
Map[Print, Sort[results, #1[[3]] < #2[[3]] &]];
pairs = {{3, "John"}, {1, "Bob "}, {2, "Jane"}, {1, "Beth"}};
{Mike Honeychurch[Ordering']: ,{1,Bob },0.01381}
{Mike Honeychurch[Ordering]: ,{1,Bob },0.016171}
{Mike Honeychurch[SortBy]: ,{1,Beth},0.036649}
{TomD[Select]: ,{1,Bob },0.042448}
{Mike Honeychurch[Position]: ,{1,Bob },0.042909}
{ruebenko[Ordering]: ,{1,Bob },0.048088}
{ruebenko[Compile]: ,{1,Bob },0.050277}
{TomD[Function]: ,{1,Bob },0.054296}
{mmorris[Sort]: ,{1,Beth},0.06838}
{mmorris[Map2]: ,{1,Bob },0.117905}
{mmorris[Map]: ,{1,Bob },0.119051}
pairs = RandomInteger[1000, {1000, 2}];
{Mike Honeychurch[Ordering']: ,{0,217},0.236041}
{ruebenko[Compile]: ,{0,217},0.416627}
{ruebenko[Ordering]: ,{0,217},0.675427}
{Mike Honeychurch[Ordering]: ,{0,217},0.771243}
{Mike Honeychurch[SortBy]: ,{0,217},2.68054}
{Mike Honeychurch[Position]: ,{0,217},2.70455}
{mmorris[Map2]: ,{0,217},26.7715}
{mmorris[Map]: ,{0,217},29.8413}
{mmorris[Sort]: ,{0,217},98.1023}
{TomD[Function]: ,{0,217},115.968}
{TomD[Select]: ,{0,217},116.78}
答案 0 :(得分:9)
你可以找到这样的所有最小值:
pos = Position[pairs, Min[pairs[[All, 1]]]]
pairs[[pos[[All, 1]]]]
如果您只想要其中一个
pos = Position[pairs, Min[pairs[[All, 1]]]][[1, 1]]
pairs[[pos]]
在我的机器上,这比你问题中列出的方法更快,我希望它对于更大的列表来说要快得多。
修改强>
实际上这还是更快 - 对于你的小清单。
pos = First@Ordering[pairs[[All, 1]]];
pairs[[pos]]
最好在您的真实生活列表中测试所有这些以确定时间。 (另请注意,SortBy[pairs,First]
比Sort
)
答案 1 :(得分:4)
这个怎么样:
pairs = {{3, "John"}, {1, "Bob"}, {2, "Jane"}, {1, "Beth"}};
{p1, p2} = Developer`ToPackedArray /@ Transpose[pairs]
cf = Compile[{{in, _Integer, 1}}, Block[{x, pos},
x = Part[in, 1];
pos = 0;
Do[
If[Part[in, i] < x,
x = Part[in, i];
pos = i;
];
, {i, Length[in]}];
pos
]]
pairs[[cf[p1]]]
你可以期待的最好是O(n)因为,你必须走一次列表,找到最小值。
这是第二个想法:
pairs = {{3, "John"}, {1, "Bob"}, {2, "Jane"}, {1, "Beth"}};
{p1, p2} = Developer`ToPackedArray /@ Transpose[pairs]
ord = Ordering[p1]
pairs[[ord[[1]]]]
答案 2 :(得分:1)
Select[pairs, #[[1]] == Min[pairs[[All, 1]]] &, 1]
给出
{{1, "Bob"}}
或者,或者:
Function[xx, Select[xx, #[[1]] == Min[xx[[All, 1]]] &, 1]]@pairs
我要求Select
只返回选择标准为真的第一个元素(因此第三个参数)
修改强>
另一种可能性:
min = Min[pairs[[All, 1]]];
pairs /. {___, {min, x_}, ___} :> {min, x}