Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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??

share|improve this question
    
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})? –  Mr.Wizard Dec 16 '12 at 23:08
add comment

6 Answers

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}} *)
share|improve this answer
add comment

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}}

share|improve this answer
add comment
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
share|improve this answer
add comment

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}}

share|improve this answer
    
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 –  Simon Woods Dec 16 '12 at 17:31
    
@SimonWoods You're right, updated. –  VLC Dec 16 '12 at 17:58
add comment

another way

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

Mathematica graphics

share|improve this answer
    
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. –  Chris Degnen Dec 16 '12 at 16:38
    
+1 for an alternate interpretation –  Mr.Wizard Dec 16 '12 at 23:02
add comment

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}}

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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