1
$\begingroup$

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?

$\endgroup$

3 Answers 3

5
$\begingroup$

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]]]]
$\endgroup$
3
  • 1
    $\begingroup$ I guess you will need an extra Abs before the Mean. $\endgroup$ Nov 8, 2012 at 18:48
  • $\begingroup$ Ah yes, I missed the lowest absolute part $\endgroup$ Nov 8, 2012 at 18:51
  • $\begingroup$ I'd use Pick[] for the purpose myself... $\endgroup$ Nov 8, 2012 at 23:21
8
$\begingroup$

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}}

$\endgroup$
3
  • $\begingroup$ 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]]&. $\endgroup$
    – Jens
    Nov 9, 2012 at 6:04
  • $\begingroup$ @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? $\endgroup$
    – Rojo
    Nov 9, 2012 at 13:22
  • $\begingroup$ 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. $\endgroup$
    – Jens
    Nov 9, 2012 at 16:11
3
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.