1
$\begingroup$

I have a multidimensional-variable list, suppose for example {{x1,y1},{x2,y2}..}. I have duplicate values for the 'x' coordinates and I need to find for the duplicate 'x' elements the corresponding minimum 'y'. A sample of this list is the following:

l1={{1, 1.43E-46}, {21, 2.79E-48}, {41, 3.22E-45}, {41,1.74E-46}, {81, 2.77E-46}, {121,9.97E-48}, {161, 1.24E-45}, {181,1.19E-45}}

I need to rewrite the list with only those elements from duplicate 'x' coordinates with a minimum value of 'y', for the former list this would be:

l1={{1, 1.43E-46}, {21, 2.79E-48}, {41,1.74E-46}, {81, 2.77E-46}, {121,9.97E-48}, {161, 1.24E-45}, {181,1.19E-45}}

Since from the duplicate coordinates 'x', the minimum 'y' is:

 {41,1.74E-46}
$\endgroup$

2 Answers 2

2
$\begingroup$

This works:

l1 = {{1, 1.43 10^-46}, {21, 2.79 10^-48}, {41, 3.22 10^-45}, {41, 
    1.74 10^-46}, {81, 2.77 10^-46}, {121, 9.97 10^-48}, {161, 
    1.24 10^-45}, {181, 1.19 10^-45}};

Map[First[SortBy[#, Last]] &, SplitBy[l1, First]]

(*
==> {{1, 1.43*10^-46}, {21, 2.79*10^-48}, {41, 1.74*10^-46}, {81,
   2.77*10^-46}, {121, 9.97*10^-48}, {161, 1.24*10^-45}, {181, 
  1.19*10^-45}}
*)

The first step is to use SplitBy with the first element as the criterion. Then the size of the last element is tested in SortBy.

$\endgroup$
2
  • 1
    $\begingroup$ @VanniaGonzalez you may want to change SplitBy[l1, First] to SplitBy[SortBy[l1,First], First], if the list is not guaranteed to be sorted by the x values already. If you add {21,5 10^-48} to the end of l1 both 21-starting pairs will appear in the output. $\endgroup$
    – evanb
    Commented Mar 12, 2015 at 18:46
  • $\begingroup$ @evanb Thanks, that's a good safety feature - I just assumed the example is representative and therefore the data are ordered by x. $\endgroup$
    – Jens
    Commented Mar 12, 2015 at 18:47
1
$\begingroup$
l1 = {{1, 1.43 10^-46}, {21, 2.79 10^-48}, {41, 3.22 10^-45}, {41,1.74 10^-46}, 
      {81, 2.77 10^-46}, {121, 9.97 10^-48}, {161, 1.24 10^-45}, {181, 1.19 10^-45}};

I version 10, you can also use MinimalBy:

    Join@@MinimalBy[Last]/@GatherBy[l1, First]
    (* {{1, 1.43*10^-46}, {21, 2.79*10^-48}, {41, 1.74*10^-46}, {81, 2.77*10^-46}, 
        {121, 9.97*10^-48}, {161, 1.24*10^-45}, {181, 1.19*10^-45}} *)

or Merge:

List@@@Normal@Merge[#->#2&@@@l1, Min]
(* {{1, 1.43*10^-46}, {21, 2.79*10^-48}, {41, 1.74*10^-46}, {81, 2.77*10^-46}, 
    {121, 9.97*10^-48}, {161, 1.24*10^-45}, {181, 1.19*10^-45}} *)
$\endgroup$

Your Answer

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

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