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.

Suppose I have a nested list such as,

{{{A, B}, {A, D}}, {{C, D}, {A, A}, {H, A}}, {{A, H}}}

Where the elements of interest are,

{{A, B}, {A, D}}

{{C, D}, {A, A}, {H, A}}

{{A, H}}

How would I use select to pick up only elements that contain two or more As in the first part of their sub-elements. In this example I would want the following as an output,

{{A,B},{A,D}}
share|improve this question
2  
This does it: Cases[{{{A, B}, {A, D}}, {{C, D}, {A, A}, {H, A}}, {{A, H}}}, {___, {A, _}, ___, {A, _}, ___}] –  Coolwater Jul 28 at 19:29
    
Yep this is exactly what I am looking for. Thank you. –  Ibrahim Jul 28 at 19:35

3 Answers 3

up vote 3 down vote accepted
list = {{{a, b}, {a, d}}, {{c, d}, {a, a}, {h, a}}, {{a, h}}}

Pick[list, Count[#[[All, 1]], a] >= 2 & /@ list]

or

Select[list, Count[#[[All, 1]], a] >= 2 &]

or

Cases[list, _?(Count[#[[All, 1]], a] >= 2 &)]

or

DeleteCases[list, _?(! Count[#[[All, 1]], a] >= 2 &)]

all give

{{{a, b}, {a, d}}}
share|improve this answer
    
This is probably the best answer, since it uses the select command explicitly. Thanks! –  Ibrahim Jul 28 at 20:23
    
@kguler executing your Select with, f.e., list = {{{a, b}, {c, a}}, {{c, d}, {a, a}, {h, a}}, {a, h}, {{a, b}, {a, c}}, {{a, b}, {q, r}, {a, d}}} I get an error message and a result which is, the question being utterly ambigous, debatable. –  eldo Jul 28 at 20:37
    
@eldo, good observation re implicit assumption that is the source of the error message: although OP's example has that structure, it is not explicitly stated that all sublists have depth >=2. However -- removing {a,h} or changing it to {{a,h}} -- I don't understand why the result is "debatable". –  kguler Jul 28 at 20:55
    
@kguler - This question has a short history of accepted and de-accepted answers and comments which were subsequently deleted. "Debatable" because the OP is unsure about what he really wants. Hopefully, your excellent answer stays awarded. (But a Case-solution would be more appropriate imo) :) –  eldo Jul 28 at 21:13
    
@eldo, I see. I missed the deleted comments. And I now see why the wording "elements that contain two or more As in the first part of their sub-elements" could be read differently from my reading of it -- of course, with the help of desired output -- as " two or more elements whose first part is equal to A" –  kguler Jul 28 at 21:23
list = {{{A, B}, {A, D}}, {{C, D}, {A, A}, {H, A}}, {{A, H}}};

If[Count[First /@ #, A] >= 2, #, ## &[]] & /@ list

{{{A, B}, {A, D}}}

share|improve this answer

I chose a slightly different formulation:

expr = {{{A, B}, {A, D}}, {{C, D}, {A, A}, {H, A}}, {{A, H}}};

Select[expr, Count[#, {A, _}] > 1 &]
{{{A, B}, {A, D}}}

I will note that this form is faster all four in the Accepted answer:

list = RandomChoice[CharacterRange["A", "H"], {500000, 3, 2}];

Select[list, Count[#, {"A", _}] > 1 &]                  // Timing // First

Pick[list, Count[#[[All, 1]], "A"] >= 2 & /@ list]      // Timing // First
Select[list, Count[#[[All, 1]], "A"] >= 2 &]            // Timing // First
Cases[list, _?(Count[#[[All, 1]], "A"] >= 2 &)]         // Timing // First
DeleteCases[list, _?(! Count[#[[All, 1]], "A"] >= 2 &)] // Timing // First

0.592804

0.795605
0.811205
0.936006
1.060807

share|improve this answer

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.