6

I have a problem that, admittedly, I have already solved using Select instead, but it is irking me that I cannot seem to construct the right pattern to solve it using Cases. I would like the output of

Cases[
    {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}},
    (* THE CORRECT PATTERN HERE *)
]

to be

{{{1, 2}, {3}, {4, 5}}, {{6}, {}}}

In other words, I would like a pattern that picks up all the elements of the outer list that have at least one non-empty list as an element.

Thanks in advance for your help.

Shredderroy
  • 5,249
  • 17
  • 26

5 Answers5

10

Here's a way, that is a bit like @kguler's, but it's simpler and a little faster:

list = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}};

Cases[list, {___, {__}, ___}]
(*
  {{{1, 2}, {3}, {4, 5}}, {{6}, {}}}
*)

The pattern ___ (three underscores or BlankNullSequence) matches zero or more things and the pattern __ (two underscores or BlankSequence) matches one or more things. So the pattern {___, {__}, ___} represents a list containing

  1. zero or more things, followed by
  2. a list containing at least one thing, followed by
  3. zero or more of things.

All in all, it matches a list that contains at least one element that is a nonempty list. Cases will match this against the elements of list at level one.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • nice. May be you explain a little for us newbies how this works :) – Nasser Aug 28 '14 at 02:15
  • Michael, this made me realize that i could also use the pattern {___, Except[{}], ___} instead of the earlier contraption {___,{___,Except[{}],___},___}... – kglr Aug 28 '14 at 02:40
8
list = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}};
Cases[list, Except[{{} ..}]]
(* {{{1, 2}, {3}, {4, 5}}, {{6}, {}}} *)

or

Cases[list, {___, Except[{}], ___}]
(* {{{1, 2}, {3}, {4, 5}}, {{6}, {}}} *)

You can also use PatternTest (_?func) where func is any selector function that you might have used as the second argument of Select. For example:

Select[list, Union @@ # =!= {} &]  (* or Flatten @ # =!= {} & or  ... *)
(* {{{1, 2}, {3}, {4, 5}}, {{6}, {}}}  *)

Cases[list, _?(Union @@ # =!= {} &)]
(*  {{{1, 2}, {3}, {4, 5}}, {{6}, {}}} *)
kglr
  • 394,356
  • 18
  • 477
  • 896
7

Unless you have other requirements I recommend DeleteCases:

list = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}};

DeleteCases[list, {{} ..}]
{{{1, 2}, {3}, {4, 5}}, {{6}, {}}}

For deletion at all levels you could use:

list /. {{} ..} -> Sequence[]
{{{1, 2}, {3}, {4, 5}}, {{6}, {}}}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • I don't think it will work for all levels. check this: {{{1, 2}, {3}, {4, 5, {5}}}, {{6}, {}, {}}, {{}, {{}, {}}}, {{}, {}, {2}}}; – Basheer Algohi Aug 28 '14 at 04:30
  • @Algohi It does work on that list but it doesn't remove the new expression {{}} that is created. That is a different interpretation from what I intended. If you with to remove that you could use //. but be aware that it is inefficient. For greater efficiency one might use: Replace[list, {({} | _Sequence) ..} -> Sequence[], {1, -1}] – Mr.Wizard Aug 28 '14 at 06:07
3

that picks up all the elements of the outer list that have at least one non-empty list as an element.

I think Except is the logical choice and more functional also. But for fun, since Length[] applied to {{}} gives zero (after Flatten), may be this can be used to check

lis = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}};
Cases[lis, x_ /; Length[Flatten@x] > 0]
     (*  {{{1, 2}, {3}, {4, 5}}, {{6}, {}}} *)

Or can do direct compare to {} (after Flatten also)

lis = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}};
Cases[lis, x_ /; Not[SameQ[Flatten@x, {}]]]
   (* {{{1, 2}, {3}, {4, 5}}, {{6}, {}}} *)

another test

lis = {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}}, {{}, {}, {2}}};
Cases[lis, x_ /; Not[SameQ[Flatten@x, {}]]]
   (* {{{1, 2}, {3}, {4, 5}}, {{6}, {}}, {{}, {}, {2}}} *)
Nasser
  • 143,286
  • 11
  • 154
  • 359
1

How a bout this for all levels:

lis = {{{1, 2}, {3}, {4, 
     5, {5}}}, {{6}, {}, {}}, {{}, {{}, {}}}, {{}, {}, {2}}};
    Select[lis , #/# =!= # || # =!= # + # &] // Quiet
      (* {{{1, 2}, {3}, {4, 5, {5}}}, {{6}, {}, {}}, {{}, {}, {2}}} *)
Basheer Algohi
  • 19,917
  • 1
  • 31
  • 78