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$

3 Answers 3

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$
2
  • $\begingroup$ This methods allows a single element to appear in multiple pairs. $\endgroup$ Dec 11, 2015 at 23:16
  • $\begingroup$ Correct. Though I did not see any restriction on that particular issue. $\endgroup$ Dec 11, 2015 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$
1
  • $\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$ Dec 12, 2015 at 22:15

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.