# Select element of list based on proximity to a certain value

I have the following matrix:

data = {{0.795718, 0.737, 0.813, 1.27301}, {0.846782, 0.767, 0.86,1.2859},
{0.742211, 0.691, 0.767, 1.27714}, {0.754719, 0.706, 0.783,1.27319},
{0.743044, 0.691, 0.783, 1.26768}, {0.745167, 0.706,0.783, 1.28189},
{0.815733, 0.752, 0.86,1.25376}, {0.551127, 0.553,0.553, 1.2084}};


each row is made up of a list of 4 elements: {x1,x2,x3,y}. I would like to apply a rule to the matrix that allows me to select, row by row, only one of the first 3 elements, the one that is closest to a certain value, let us say xbest (eg 0.8 in the example with the data above), let us call this element xwin. Eventually, I would like have a new matrix with rows of 2 elements only: {xwin,y}. Your help is appreciated.

This seems like a good case for NearestTo:

NearestTo[x]
is an operator form that yields Nearest[elems, x] when applied to a list elems.

nTo = NearestTo[xbest, 1];
Join[nTo /@ data[[All, ;; 3]], data[[All, {4}]], 2]


{{0.795718, 1.27301}, {0.767, 1.2859}, {0.767, 1.27714}, {0.783, 1.27319}, {0.783, 1.26768}, {0.783, 1.28189}, {0.815733, 1.25376}, {0.553, 1.2084}}

• Nice! I didn't know of this new function! Do you know how does it compare with Nearest in terms of efficiency? Commented Jun 29, 2018 at 8:23
• @Fraccalo, it seems that for long lists they are similar, but shorter lists, to my surprise, Nearest is much faster: dt=RandomInteger[100000,s]; NearestTo[99]@dt// RepeatedTiming versus Nearest[dt, 99]// RepeatedTiming  for s=100 and s = 10^6.
– kglr
Commented Jun 29, 2018 at 8:54
• I am using v10.0 and NearestTo is not defined there. How to circumvent this? and how to get the element (from the first 3) that is the furthest away from xBest? Commented Jun 29, 2018 at 9:23
• @Luigi, NearestTo is new in v11.3. I would go with Fraccalo's answer for finding nearest and farthest elements.
– kglr
Commented Jun 29, 2018 at 9:31
• @kglr Thanks for the benchmark! And yes, the discrepancy in the speed depending on the list length is quite weird Commented Jun 29, 2018 at 10:12

xBest = 0.8;
{First@Nearest[#[[1 ;; 3]], xBest], #[[4]]} & /@ data


And for the "Farthest" function:

xBest = 0.8;
{First@Nearest[#[[1 ;; 3]], xBest,
DistanceFunction -> (-Abs[#1 - #2] &)], #[[4]]} & /@ data

• could work! however, if you apply it to data, you see that the last row has duplicated value (3 elements rather than 2). With xBest=0.8058 you get {{0.813, 1.27301}, {0.767, 1.2859}, {0.767, 1.27714}, {0.783, 1.27319}, {0.783, 1.26768}, {0.783, 1.28189}, {0.815733, 1.25376}, {0.553, 0.553, 1.2084}} as result. Commented Jun 28, 2018 at 20:40
• Check the last edit :D Commented Jun 28, 2018 at 20:43
• Now, how to select the element that is furthest away from xBest. In other words, what is the opposite of Nearest? thanks! Commented Jun 29, 2018 at 6:43
• See new edit to my answer Commented Jun 29, 2018 at 8:06

Using TakeLargestBy and TakeSmallestBy:

Clear["Global*"];
xbest = 0.8;

data = {{0.795718, 0.737, 0.813, 1.27301}, {0.846782, 0.767, 0.86,
1.2859}, {0.742211, 0.691, 0.767, 1.27714}, {0.754719, 0.706,
0.783, 1.27319}, {0.743044, 0.691, 0.783, 1.26768}, {0.745167,
0.706, 0.783, 1.28189}, {0.815733, 0.752, 0.86,
1.25376}, {0.551127, 0.553, 0.553, 1.2084}};

nearest =
TakeSmallestBy[EuclideanDistance[#, xbest] &, 1] /@
data[[All, 1 ;; 3]];
last = data[[All, {4}]];
farthest =
TakeLargestBy[EuclideanDistance[#, xbest] &, 1] /@
data[[All, 1 ;; 3]];

`