# Find the first n pairs in a list whose difference is the nearest to some number

This is my list:

list = {2.6135182051634342, -2.6690957180727297,
0.26060239174734157, -0.4182243295792278};


I wanna gather it every two number,which make this group's diffrence's absolute value is nearest 3.14.

We can see this distance martix.

 DistanceMatrix[list,
DistanceFunction -> (First[Abs[#1 - #2]] &)] // MatrixForm


As we see.The $(1st,4th)$ and $(2nd,3rd)$ is we want to group.Implies we result is {{2.6135182051634342,-0.4182243295792278},{-2.6690957180727297,0.26060239174734157}}

But this code doesn't work,becuase the Nearest's first parameter cannot be a matrix.

mat = DistanceMatrix[list,
DistanceFunction -> (First[Abs[#1 - #2]] &)];
Position[mat, Nearest[mat, 3.14, 2]]


Or there are other more better method to do this?

Let's extended this topic.Assumption we have a list2 like this.But wanna group it every two element that make its sum nearest 100.So how to do it?

SeedRandom[2016317];
list2 = RandomSample[Range@100, 20];
DistanceMatrix[list,
DistanceFunction -> (First[Plus[#1, #2]] &)] // MatrixForm


• @Dr.belisarius Can we don't set a threshold value?Because the value is not easy to confirm at times.
– yode
Mar 17, 2016 at 3:28
• You didn't mention "without element repetitions" in your first formulation of the question. Moving target questions are generally frowned upon here and I, for one, don't answer them anymore as they are an endless process. Mar 20, 2016 at 16:30
• @Dr.belisarius The poor language competence undermining me.I didn't deliberately frown you.Actually the function is used in this to judge whether two points are in a line.I felt very very upset for letting you down.And I post a new quetion for this "new target".
– yode
Mar 21, 2016 at 1:20
• Ok, no prob. :) Mar 21, 2016 at 1:21

f[l_List, nbr_Integer, near_Real] := Module[{k, f},
k = Subsets[Range@Length@l, {2}];
f = Nearest[# -> Range@Length@#] &[EuclideanDistance @@ l[[#]] & /@ k];
k[[f[near, nbr]]]
]

list = {2.6135182051634342, -2.6690957180727297,
0.26060239174734157, -0.4182243295792278};

f[list, 2, N@Pi]

(* {{1, 4}, {2, 3}} *)


SeedRandom[2016317];
list2 = RandomSample[Range@100, 20];
f[list2, 2, 100.]

(* {{14, 18}, {18, 20}} *)

• we result is {{2.6135182051634342,-0.4182243295792278},{-2.6690957180727297,0.26060239174734157}}.Of course,your code can do it.
– yode
Mar 17, 2016 at 3:30
• I'm sorry to cancel the acceptance.But some problem isn't be found before this.
– yode
Mar 20, 2016 at 9:32

I'll show how to use Nearest for this, using the larger example.

SeedRandom[2016317];
list2 = RandomSample[Range@100, 20]

(* Out[1510]= {20, 42, 89, 8, 56, 96, 39, 21, 40, 76, 62, 14, 51, 5,
66, 84, 73, 99, 37, 7} *)

nf = Nearest[list2];


Now we use the fact that the NearestFunction can take a list argument (shortcut for mapping in this case) when dimensions are appropriate. For each element we want to find the one(s) that with it sum closest to 100.

nf[100 - list2]

(* Out[1507]= {{76, 84}, {56}, {8,
14}, {89}, {42}, {5}, {62}, {76}, {62}, {21}, {39,
37}, {84}, {51}, {96}, {37}, {14}, {21}, {5}, {62}, {96}} *)


--- edit ---

Here is how one can restrict so that we only keep values that come within a threshold of the goal. I'll also use Map so that this will work in versions prior to Mathematica 10.1 or so.

Cases[
Map[{#, nf[100 - #, {Infinity, 1.5}]} &, list2], {_, {__}}]

(* Out[1590]= {{96, {5}}, {39, {62}}, {62, {39,
37}}, {5, {96}}, {37, {62}}} *)


--- end edit ---

• Fails on v9. Is it a v10 feature? Mar 17, 2016 at 17:56
• The listability is, yes. In v9 I guess use Map. Mar 17, 2016 at 18:28
• Thanks for your answer.But I'm very sorry for misunderstanding your meaning.As the Dr.belisarius's coustom function f,I can get the result like this list2[[#]]&/@f[list2,2,100.].But you?
– yode
Mar 17, 2016 at 22:05
• Why not also show the version for 10.1 and above Mar 17, 2016 at 22:35