Pick elements of largest absolute value
(Edited with a slight tweak for a tiny bit more speed)
For the non-duplicate version I am finding this quite fast:
f = If[+## > 0, ##] & @@ {Max[#], Min[#]} &
f /@ list
(* {-5, 6, 4, -9} *)
I'd use Ordering
, as Nasser did, but with the default sort as it will be much faster:
# ~Extract~ Ordering[Abs@#, -1] & /@ list
{-5, 6, 4, -9}
If duplicates are required we can substitute Position but Pinguin Dirk's method is faster.
list = {{1, -3, -5}, {2, 1, 6}, {0, 2, 4}, {-9, 2, 6}, {1, -2, 2}}
# ~Extract~ (Position[#, Max@#] &@Abs@#) & /@ list
{{-5}, {6}, {4}, {-9}, {-2, 2}}
Here is a concise use of Pick
that appears to be competitive for the with-duplicates case:
f[a_] := Pick[a, #, Max@#] & @ Abs @ a
f /@ list
{{-5}, {6}, {4}, {-9}, {-2, 2}}
Timings in version 7 (Pick
should be faster in v8 and after):
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]
list = RandomInteger[{-30, 30}, {50000, 20}];
# ~Extract~ (Position[#, Max@#] &@Abs@#) & /@ list // timeAvg
Pick[list, UnitStep[# - Max[#]] & /@ (Abs@list), 1] // timeAvg
f /@ list // timeAvg
0.2496
0.2184
0.1996
Nasser's timings in version 9 are: 0.328, 0.112, 0.203 showing that Pinguin Dirk's code is by far the fastest in recent versions.
And timings for the non-duplicate methods:
list = RandomReal[{-9, 9}, {50000, 20}];
# ~Extract~ Ordering[Abs@#, -1] & /@ list // timeAvg
(SortBy[#, Abs] & /@ list)[[All , -1]] // timeAvg
If[+## > 0, ##] & @@ {Max[#], -Max[-#]} & /@ list // timeAvg
Pick[Flatten@#, Flatten[Ordering@Ordering@Abs[#] & /@ #], 3] &@list // timeAvg
MapThread[Extract, {list, Ordering[#, -1, (Abs@#1 < Abs@#2) &] & /@ list}] // timeAvg
Max /@ Pick[list, UnitStep[# - Max[#]] & /@ (Abs@list), 1] // timeAvg
0.078
0.1092
0.128
0.2308
0.842
0.2652
With the clarification, I think I can reuse my solution I initially provided by just mapping Max
over it again:
Old:
Pick[list, UnitStep[# - Max[#]] & /@ (Abs@list), 1]
New:
Max /@ Pick[list, UnitStep[# - Max[#]] & /@ (Abs@list), 1]
(note: the old solution returned any value that has max abs value, i.e. {1,2,-2}
returned 2,-2
).
Based on this new information, this approach is definitely not the best out there, see @Mr.Wizard's answer.