9
$\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$
5
  • 5
    $\begingroup$ DeleteCases[list, {{} ..}] $\endgroup$
    – ciao
    Commented Sep 20, 2015 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
    Commented Sep 20, 2015 at 21:47
  • $\begingroup$ Related: (1276), (20180) $\endgroup$
    – Mr.Wizard
    Commented Sep 21, 2015 at 7:39
  • 1
    $\begingroup$ Why close votes for "does not concern software Mathematica ..." reason?! $\endgroup$ Commented Sep 21, 2015 at 12:52
  • $\begingroup$ Related: "Efficient way to remove empty lists from lists?" $\endgroup$ Commented Aug 24, 2016 at 9:39

4 Answers 4

9
$\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$
2
  • $\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$ Commented Sep 22, 2015 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
    Commented Sep 22, 2015 at 7:24
10
$\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$
6
  • 1
    $\begingroup$ Since OP mentions "efficient", I think this will be considerably slower than DeleteCases on large lists... $\endgroup$
    – ciao
    Commented Sep 21, 2015 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
    Commented Sep 21, 2015 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
    Commented Sep 21, 2015 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
    Commented Sep 21, 2015 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
    Commented Sep 21, 2015 at 8:25
10
$\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$
5
  • $\begingroup$ Give DeleteCases[Map[Flatten, b, {2}], {{} ..}] a whirl... $\endgroup$
    – ciao
    Commented Sep 21, 2015 at 8:34
  • $\begingroup$ for fun i was going to post FixedPoint[# /. {} -> Sequence[] &, b] but pointless really...felt like popping bubblewrap. $\endgroup$
    – ubpdqn
    Commented Sep 21, 2015 at 8:36
  • 1
    $\begingroup$ @ubpdqn or like this :b//. {} -> Sequence[] $\endgroup$
    – xyz
    Commented Sep 21, 2015 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
    Commented Sep 21, 2015 at 9:20
  • $\begingroup$ Thanks ubqdqn. Elegant code - I should have looked at the problem from a different perspective. $\endgroup$ Commented Sep 22, 2015 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 and acknowledge you have read our privacy policy.

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