3
$\begingroup$

I have two long lists (of different lengths) of complex numbers. There seem to be some close pairings, so I'd like to explicitly pair elements from each list with their nearest counterpart in the other list.

Example, with small Reals for simplicity:

a={0.13, 0.83, 0.79, 0.61, 0.91, 0.99, 0.4};
b={0.72, 0.02, 0.69, 0.37, 0.14};

For this example, I'd like to pair these up by Min[Abs[a[[i]]-b[[j]]]] where Abs[a[[i]]-b[[j]]]<.1

Desired result:

$$ \left( \begin{array}{c} \{0.13,0.4,0.61,0.79\} \\ \{0.14,0.37,0.69,0.72\} \\ \{0.83,0.91,0.99\} \\ \{0.02\} \\ \end{array} \right) $$

The first two rows match the respective matching elements from a and b. The 3rd and 4th rows are the unmatched elements from respectively a and b.

Is there some way to do this efficiently with Mathematica functions?

$\endgroup$
4
$\begingroup$

This should be fairly efficient for large examples.

a = {0.13, 0.83, 0.79, 0.61, 0.91, 0.99, 0.4};
b = {0.72, 0.02, 0.69, 0.37, 0.14};

nf = Nearest[b];
ntable = Table[nf[aj, {1, .1}], {aj, a}];
row1 = Pick[a, ntable, {_}];
row2 = Flatten[ntable];
row3 = DeleteCases[a, Alternatives @@ row1];
row4 = DeleteCases[b, Alternatives @@ row2];
{row1, row2, row3, row4}

(* Out[280]= {{0.13, 0.79, 0.61, 0.4}, {0.14, 0.72, 0.69, 0.37}, {0.83, 
  0.91, 0.99}, {0.02}} *)
$\endgroup$
  • $\begingroup$ This methods allows a single element to appear in multiple pairs. $\endgroup$ – Jerry Guern Dec 11 '15 at 23:16
  • $\begingroup$ Correct. Though I did not see any restriction on that particular issue. $\endgroup$ – Daniel Lichtblau Dec 11 '15 at 23:26
2
$\begingroup$
a = {0.13, 0.83, 0.79, 0.61, 0.91, 0.99, 0.4};
b = {0.72, 0.02, 0.69, 0.37, 0.14};

Table[{b[[i]], Nearest[a, b[[i]]][[1]]}, {i, Length[b]}]

(* {{0.72, 0.79}, {0.02, 0.13}, {0.69, 0.61}, {0.37, 0.4}, {0.14, 0.13}} *)

If you want only pairs closer than 0.5 (for instance):

Select[Table[{b[[i]], Nearest[a, b[[i]]][[1]]}, {i, Length[b]}], 
 Norm[#] < .5 &]

(* {{0.02, 0.13}, {0.14, 0.13}} *)

$\endgroup$
2
$\begingroup$
a = {0.13, 0.83, 0.79, 0.61, 0.91, 0.99, 0.4};
b = {0.72, 0.02, 0.69, 0.37, 0.14};

near[a_, b_, th_] :=
   Module[{x, y},
      x = {#, Nearest[b, #]} & /@ a /. {p_, {q_}} :> {p, q, Abs[p - q]};
      y = Select[x, Last@# < th &];
      {
       Sort@y[[All, 1]],
       Sort@y[[All, 2]],
       Complement[x, y][[All, 1]],
       Complement[b, x[[All, 2]]]
       }]

near[a, b, 0.1] // MatrixForm

enter image description here

$\endgroup$
  • $\begingroup$ I don't know if it matters in terms of the desired final result, but Complement will reorder. If a sorted order is what is wanted then it is definitely the way to go. $\endgroup$ – Daniel Lichtblau Dec 12 '15 at 22:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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