4
$\begingroup$

I have a list like:

   {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, 
    {{4, 18}, 1}, {{4, 14}, 3},  {4,15},      {{4, 16}, 2},{4,18}}

Now I want to filter this list. First I want to delete lists that have the form: {a,b} like {4,15} and {4,18}. So what remains is:

 {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, 
  {{4, 18}, 1}, {{4, 14} ,3}, {{4, 16}, 2}}

And now I want only the lists which are a minimum: For example now you have a list with:

{{4, 14}, 1} and {{4, 14}, 3}
{{4, 16}, 1} and {{4, 16}, 2}

I want that only {{4, 14}, 1} and {{4, 16}, 1} remain (minimum of the third number).

Finally remains:

{{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}

How can I easily do this??

$\endgroup$
1
  • 1
    $\begingroup$ Glenn, as you can see from the answers below there is ambiguity in your question. Do you want to return only elements of the form {{_, _}, min} where min is the global minimum across all lists, or rather elements where min is the smallest value within the set that share a common first part (e.g. {4, 14})? $\endgroup$
    – Mr.Wizard
    Dec 16 '12 at 23:08
6
$\begingroup$

Yet another way using Select and GatherBy:

list = {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 
    1}, {{4, 18}, 1}, {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}};
x1 = Select[list, Length[#[[1]]] == 2 &];
x2 = GatherBy[x1, First];
(Sort[#] & /@ x2)[[All, 1]]

{{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}}

$\endgroup$
2
  • $\begingroup$ You could use SortBy[#,Last] instead of Sort[#, #1[[2]] < #2[[2]] &] . Or, for this problem, just Sort since the first elements are all the same $\endgroup$ Dec 16 '12 at 17:31
  • $\begingroup$ @SimonWoods You're right, updated. $\endgroup$
    – VLC
    Dec 16 '12 at 17:58
4
$\begingroup$

another way

list = DeleteCases[list, {x_Integer, y_Integer}];
min = Min[list[[All, 2]]];
Extract[list, Position[list[[All, 2]], min] ]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ You're assuming the minimum (third number) is just going to be one number, in this case 1, but it seems the different lists could have various minimum numbers. $\endgroup$ Dec 16 '12 at 16:38
4
$\begingroup$
lst = {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1},
       {{4, 17}, 1}, {{4, 18}, 1}, {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}}

First /@ Sort /@ GatherBy[Cases[lst, {_List, _}], First]
{{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}}

Or with ~infix~:

First /@ Sort /@ lst ~Cases~ {_List, _} ~GatherBy~ First
$\endgroup$
2
$\begingroup$

Here's a fairly simple way of doing it:-

x = {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1},
     {{4, 18}, 1}, {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}};
x2 = Replace[x, {a_Integer, b_Integer} -> Null, {1}];
x3 = DeleteCases[x2, Null];
types = Union[x3[[All, 1]]];
First[Sort[Cases[x3, {#, _}]]] & /@ types

{{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}}

$\endgroup$
2
$\begingroup$

An approach based on Cases:

lst = {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1},
   {{4, 17}, 1}, {{4, 18}, 1}, {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}}

Cases[list, {{_, _}, Min[list /. {{_, _}, x_} -> x]}]

{{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}}

$\endgroup$
1
$\begingroup$

With

x = {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, 
  {{4, 18}, 1}, {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}};
x2 = {{{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}, 
  {{4, 14}, 3}, {4, 15}, {{4, 16}, 2}, {4, 18}, {{4, 14}, 2}};

you can also use

 Union[Cases[x, {{ _, _ }, _}], SameTest -> (First@#1 == First@#2 &)]

or

 (* if the elements `{{a,b}, c}` are already sorted with respect to the the last entry:*)
 DeleteDuplicates[Cases[x, {{_, _}, _}], (#1[[1]] == #2[[1]] &)] 
 (* if not: *)
 DeleteDuplicates[SortBy[#, Last] &@Cases[x, {{_, _}, _}], (#1[[1]] == #2[[1]] &)]

to get:

(* {{{4, 14}, 1}, {{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}} *)

Update: Further alternatives that preserve the ordering of the input list:

cleanUp2[x_] :=  With[{gthrd = GatherBy[Select[x, Depth[#] == 3 &], First]},
   Join @@ Pick[#, Last /@ #, Min @@ (Last /@ #)] & /@ gthrd];
cleanUp3[x_] := DeleteCases[x, Alternatives[{_Integer, _},
    {w : {_, _}, z_} /; z > Min @@ Last /@ Cases[x, {w, _}]]]; 
cleanUp4[x_] :=  Cases[x, {w : {_, _}, z_} /; z == Min @@ Last /@ Cases[x, {w, _}]];

Example:

 cleanUp3[x2]
 (* {{{4, 15}, 1}, {{4, 16}, 1}, {{4, 17}, 1}, {{4, 18}, 1}, {{4, 14}, 2}} *)
$\endgroup$

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.