1

Given that there is a set of points, for example, {{3,4,2},{5,2,-1}}. How do I go about selecting the point that has the lowest absolute x, y or z-coordinate from the list? In this case, the point selected should be {{5,2,-1}} as 1 is the lowest absolute value among all the points. Would the command Select[{{3,4,2}, {5,2,-1}}, ...] be good enough to perform such operation? Specifically, my understanding is that Select[{{3,4,2}, {5,2,-1}}, ...] is useful for selecting each individual point that satisfies certain condition stated in the command, so the question is whether it would be possible to compare 2 different points to select the desired point under the Select[...] operation. Or would there be a better alternative to getting the desired point?

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Markeur
  • 95
  • 3

3 Answers3

8

Select only looks at each element in the list to decide if it stays or it doesn't, much like Cases. Some options

f1 = Extract[#, (First@Position[Flatten@Abs@#, Min@Abs@#] + 2)~Quotient~3] &;
f2 = Extract[#, Ordering[#, 1, Min@Abs@#1 < Min@Abs@#2 &]] &;
f3 = First@SortBy[#, Min@Abs@# &] &;
f4 = First@Nearest[#, {0`, 0`, 0`}, DistanceFunction -> (Min@Abs[#2 - #1] &)] &;
f5 = Extract[#, Ordering[Min /@ Abs@#, 1]] &;
f6 = Extract[#, (Ordering[Abs@Flatten@#, 1] + 2)~Quotient~3] &;

So

f1[r] // AbsoluteTiming
f2[r] // AbsoluteTiming
f3[r] // AbsoluteTiming
f4[r] // AbsoluteTiming
f5[r] // AbsoluteTiming
f6[r] // AbsoluteTiming

gives

{0.1760238, {-12.1516, 56.6547, -0.000243945}}

{0.8061080, {-12.1516, 56.6547, -0.000243945}}

{0.0430082, {-12.1516, 56.6547, -0.000243945}}

{1.1661187, {-12.1516, 56.6547, -0.000243945}}

{0.0150015, {-12.1516, 56.6547, -0.000243945}}

{0.0060008, {-12.1516, 56.6547, -0.000243945}}

Rojo
  • 42,601
  • 7
  • 96
  • 188
  • Interesting comparisons. For your last one, f6, I got an additional speed boost by omitting the unused coordinates from the argument of Ordering: f7=Extract[#1,Ordering[Abs[#1[[All,1]]],1]]&. – Jens Nov 09 '12 at 06:04
  • @Jens, I understood he wanted the minimum abs of any of the three coordinates, your suggested code would only look at the first one, right? – Rojo Nov 09 '12 at 13:22
  • Oh, right. I'm solving a different problem - If I do my approach for each component separately, I think your f6 wins the speed comparison again. – Jens Nov 09 '12 at 16:11
5

Since Min returns the smallest element of any of the lists, you can use Position:

list = RandomReal[1, {50, 3}];
list[[Position[list, Min[Abs@list]][[1, 1]]]]
David Slater
  • 1,525
  • 10
  • 13
3

There's a little function I call MinBy I like to use from time to time (see here). It relates to Min the same way SortBy relates to Sort.

MinBy[list_, fun_] := list[[First@Ordering[fun /@ list, 1]]]

This function gives yet another simple solution to your question:

points = {{3, 4, 2}, {5, 2, -1}}
MinBy[points, Composition[Min, Abs]]

Note that an inherent problem with using MinBy is that is always returns only a single result, even if there are several equivalent elements of the list that could be considered minimal. This solution will always return only a single point.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263