8
$\begingroup$

What is the most efficient method for deleting a row of empty list elements? For example, here is a list with one row of empty list elements:

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

I want to get rid of the whole of row 2. Using DeleteCases[]:

DeleteCases[list, x_ /; x == {}, Infinity]

...which returns:

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

How can I efficiently delete the 2nd row without using DeleteCases[] twice?

$\endgroup$
  • 4
    $\begingroup$ DeleteCases[list, {{} ..}] $\endgroup$ – ciao Sep 20 '15 at 21:35
  • $\begingroup$ As an aside, if your list "empties" are known to have the same structure, you can get a nice performance boost by specifying the exact pattern, e.g. DeleteCases[list, {{}, {}, {}}] in your example. $\endgroup$ – ciao Sep 20 '15 at 21:47
  • $\begingroup$ Related: (1276), (20180) $\endgroup$ – Mr.Wizard Sep 21 '15 at 7:39
  • 1
    $\begingroup$ Why close votes for "does not concern software Mathematica ..." reason?! $\endgroup$ – Leonid Shifrin Sep 21 '15 at 12:52
  • $\begingroup$ Related: "Efficient way to remove empty lists from lists?" $\endgroup$ – Alexey Popkov Aug 24 '16 at 9:39
8
$\begingroup$

I don't have the same interpretation of OP requirements as others seem to, but here's my take on those interpretations:

DeleteCases[#, Nest[{# ...} &, {}, Depth[#]], Infinity] &@b

Where b is of course the target list.

Unless Nothing performs much faster than the use of Sequence[], this seems to do quite well against what appears to be the fastest "get rid of any empty list anywhere" solution.

Edit: I used this to generate test b:

b = 
 RandomChoice[
  {9, 1, 1, 1, 9} -> 
   {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
    {{}, {}, {}}, {{}, {{{}, {{}}, {}}}, {}}, {{}}, 
    {{1, 2, 3}, {}, {{{{{{{{{{{{1, 2, 3, {{{}, {1, 2, 3}}}}}}}}}}}}}}},
     {1,2, 3, {}}}}, 1000000];
$\endgroup$
  • $\begingroup$ Nice example. I spent a little time figuring out how this works. Would I be correct in saying that in this case, the condition in the DeleteCases function is the a representation of the empty list structure? Doing this causes the DeleteFunction to delete empty lists in one go without mapping or nesting DeleteCases? Thanks to all who gave their time to help me. $\endgroup$ – awyr_agored Sep 22 '15 at 7:18
  • 1
    $\begingroup$ @awyr_agored: Yes, though what "one go" means under the covers can vary. In any case, it handily outperformed in my tests, glad you find in useful and interesting. $\endgroup$ – ciao Sep 22 '15 at 7:24
9
$\begingroup$

Here is a very simple and concise construct for doing what you ask.

a = 
  {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
   {{}, {}, {}}, 
   {{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}};
a //. {} -> Nothing
{{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
 {{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}}

It has the advantage of working for { } appearing at any level.

b = 
  {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
   {{}, {}, {}}, 
   {{}, {{{}, {{}}, {}}}, {}}};
b //. {} -> Nothing
{{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}}

Note that I used the very useful new symbol Nothing. This means the above solution only works for V10.2 or later.

$\endgroup$
  • 1
    $\begingroup$ Since OP mentions "efficient", I think this will be considerably slower than DeleteCases on large lists... $\endgroup$ – ciao Sep 21 '15 at 7:30
  • $\begingroup$ @ciao I am actually having trouble beating by a large margin. DeleteCases by itself doesn't get everything in one pass. $\endgroup$ – Mr.Wizard Sep 21 '15 at 8:06
  • $\begingroup$ @Mr.Wizard: Perhaps I've misread the question - can you give an example? The OP says nothing about "arbitrarily nested..." $\endgroup$ – ciao Sep 21 '15 at 8:17
  • $\begingroup$ @ciao I mean for the case of arbitrary nesting; using m_goldberg's b if we do DeleteCases[b, {{} ...}, {0, -1}] we still end up with {{{}}} in the output. $\endgroup$ – Mr.Wizard Sep 21 '15 at 8:19
  • $\begingroup$ @Mr.Wizard: Ah, well unless Nothing is way faster than Sequence, FixedPoint[DeleteCases[#, {{} ..}, -1] &, list] is faster on the loungebook on v9 for big lists with arbitrary nesting of empties. $\endgroup$ – ciao Sep 21 '15 at 8:25
9
$\begingroup$

For arbitrarily nested lists one could also use MapAll and the operator form of DeleteCases:

b = (* m_goldberg's example *)
  {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
   {{}, {}, {}}, 
   {{}, {{{}, {{}}, {}}}, {}}};

DeleteCases[{}] //@ b
{{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}}

It works via the bottom-up standard evaluation order.

This however is somewhat slower than //. in a single test. Using an anonymous function instead of the operator form is a little faster than //. however in the same test, though less clean:

DeleteCases[#, {}] & //@ b
{{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}}
$\endgroup$
  • $\begingroup$ Give DeleteCases[Map[Flatten, b, {2}], {{} ..}] a whirl... $\endgroup$ – ciao Sep 21 '15 at 8:34
  • $\begingroup$ for fun i was going to post FixedPoint[# /. {} -> Sequence[] &, b] but pointless really...felt like popping bubblewrap. $\endgroup$ – ubpdqn Sep 21 '15 at 8:36
  • 1
    $\begingroup$ @ubpdqn or like this :b//. {} -> Sequence[] $\endgroup$ – xyz Sep 21 '15 at 9:16
  • $\begingroup$ @ShutaoTANG yes I was being silly...and ReplaceAll is what I use a lot...I guess is not about DeleteCases...:-) $\endgroup$ – ubpdqn Sep 21 '15 at 9:20
  • $\begingroup$ Thanks ubqdqn. Elegant code - I should have looked at the problem from a different perspective. $\endgroup$ – awyr_agored Sep 22 '15 at 6:53
4
$\begingroup$

This one performs nicely also:

f[{}]=Sequence[];
f[x_]:=x;

f //@ {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, {{}, {}, {}}, {{}, {{{}, {{}}, {}}}, {}}};

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

Here are some interesting relative timings for the different solutions given in this post (1.00 is the best and reference time):

enter image description here

(the test list b is Ciao's random list with parameter n as the given "size":)

SeedRandom[299];
b = RandomChoice[
  {9, 1, 1, 1, 9} -> 
   {{{1, 2, 3}, {0, 0, 0}, {4, 5, 6}}, 
    {{}, {}, {}}, {{}, {{{}, {{}}, {}}}, {}}, {{}}, 
    {{1, 2, 3}, {}, {{{{{{{{{{{{1, 2, 3, {{{}, {1, 2, 3}}}}}}}}}}}}}}},
     {1,2, 3, {}}}}, n];
$\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.