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.

There are numerous examples here, whose end result is the removal of empty brackets {} and empty lists. I still can't find an example of simply removing redundant brackets though.

It's hard for me to believe there isn't already a common solution to this problem. Please point me there if I missed it. As I am new to Mathematica I am learning primarily by example so when I ran into this problem I was at a loss of where to even start.

For example I have this list as INPUT to a new function:

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

I would like the new function to generate this list as OUTPUT:

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


The actual input TO new function:

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

The actual output FROM new function:

{{{0, 5}, {1, 4}, {2, 3}, {3, 2}, {4, 1}, {5, 0}}, {{1, 5}, {2, 4}, {3, 3}, {4, 2}, {5, 1}}, {{2, 5}, {3, 4}, {4, 3}, {5, 2}}, {{3, 5}, {4, 4}, {5, 3}}, {{4, 5}, {5, 4}}, {{5, 5}, {5, 5}}}
share|improve this question
    
Your example following "At this point' makes no sense, because expressions like (t,c) have no meaning, nor do expressions enclosed in square brackets. Otherwise, it appears you are asking to apply a replacement rule like //. {a_List->a} to your expressions. Is that what you're looking for? –  whuber Feb 25 '13 at 14:44
    
Did you look at Flatten command. Flatten[%, 1] should help. –  s.s.o Feb 25 '13 at 14:45
1  
@s.s.o Flatten will only help if the extra brackets are at a particular level. If the idea is to get rid of extra brackets anywhere in the expression something else will be needed. I think my replacement rule is probably the simplest way. –  Mr.Wizard Feb 25 '13 at 14:46
    
@ Mr.Wizard true but you don't know how many open and closed brackets you should remove as well :) İn this case you choose 2... –  s.s.o Feb 25 '13 at 14:50
1  
@s.s.o No, I used //. so that it will keep applying the rule until all extraneous brackets are gone. Probably not the most efficient way, but it should be effective. –  Mr.Wizard Feb 25 '13 at 14:51
show 1 more comment

1 Answer 1

up vote 27 down vote accepted

Starting with:

a = {{{{0, 5}, {1, 4}, {2, 3}, {3, 2}, {4, 1}, {5, 0}}}, {{{1, 5}, {2, 4}, {3, 3}, {4, 
      2}, {5, 1}}}, {{{2, 5}, {3, 4}, {4, 3}, {5, 2}}}, {{{3, 5}, {4, 4}, {5, 3}}}, {{{4, 
      5}, {5, 4}}}, {{{5, 5}}, {{5, 5}}}};

This is probably the simplest:

a //. {x_List} :> x

A single-pass method

Though using ReplaceRepeated is pleasingly concise it is not efficient with deeply nested lists. Because ReplaceAll and ReplaceRepeated scan from the top level the expression will have to be scanned multiple times.

Instead we should use Replace which scans expressions from the bottom up. This means that subexpressions such as {{{{6}}}} will have redundant heads sequentially stripped without rescanning the entire expression from the top. We can start scanning at levelspec -3 because {{}} has a Depth of 3; this further reduces scanning.

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

Replace[expr, {x_List} :> x, {0, -3}]
{{1, 2}, {3}, {4, 5}, {6}}

Here I will use FixedPointList in place of ReplaceRepeated to count the number of times the expression is scanned in the original method:

Rest @ FixedPointList[# /. {x_List} :> x &, expr] // Column
{{1,2},{3},{{4,5}},{{{6}}}}
{{1,2},{3},{4,5},{{6}}}
{{1,2},{3},{4,5},{6}}
{{1,2},{3},{4,5},{6}}

We see that the expression was scanned four times, corresponding to the three levels that were stripped from {{{{6}}}} plus an additional scan where nothing is changed, which is how both FixedPointList and ReplaceRepeated terminate. To see the full extent of this scanning try:

expr //. {_?Print -> 0, {x_List} :> x};

Or to merely count the total number of matches attempted:

Reap[expr //. {_?Sow -> 0, {x_List} :> x}][[2, 1]] // Length
50

We see that only 7 expressions in total are scanned with the single-pass method:

Reap[
  Replace[expr, {_?Sow -> 0, {x_List} :> x}, {0, -3}]
][[2, 1]] // Length
7

Timings

Let us compare the performance of these two methods on a highly nested expression.

fns = {Append[#, RandomInteger[9]] &, Prepend[#, RandomInteger[9]] &, {#} &};

SeedRandom[1]
big = Nest[RandomChoice[fns][#] & /@ # &, {{1}}, 10000];
Depth[big]
3264
big //. {x_List} :> x                           // Timing // First
Replace[big, {x_List} :> x, {0, -3}] ~Do~ {800} // Timing // First
0.452

0.468

On this huge expression the single-pass Replace is about 800 times faster than //..

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.