8

I have a series of lists in the form below:

list={ {1,1} , {2,2}, {3,{3,1},{3,2},{31,{31,1},{32,2}}} }

Its a nested list which the dimension is changing case to case. I want to manipulate the list to have an output like this:

LIST={{1,1},{2,2},{3,3,1},{3,3,2},{3,31,31,1},{3,31,32,2}}

I am trying to use this ReplaceList rule

list //. {a_, {b___}} :> {a, b}

But it is not working at all!! How should I make a list out of this nested list?

Morry
  • 585
  • 2
  • 11

3 Answers3

10

The problem: your pattern, {a_, {b___}} will only match a list with exactly two elements, the second of which has to be a list. As you can see, there is no such list anywhere in your expression, which is why it doesn't work.

You can correct it as follows:

sol = list //. {h__Integer, t__List} :> Map[{h} ~Join~ # &, {t}]
(* {{1, 1}, {2, 2}, {{3, 3, 1}, {3, 3, 2}, {{3, 31, 31, 1}, {3, 31, 32, 2}}}} *)

Note that the lists have the correct elements, but are nested. You can again employ rules to "flatten" them out with:

FixedPoint[Replace[#, {x__List} :> x, {1, Infinity}] &, sol]
(* {{1, 1}, {2, 2}, {3, 3, 1}, {3, 3, 2}, {3, 31, 31, 1}, {3, 31, 32, 2}} *)
rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • How to get ride of the nests to a certain level? I mean to get a result like this {{1,1},{2,2},{3,3,1},{3,3,2},{3,31,{31,1}},{3,31,{32,2}}} – Morry Aug 18 '13 at 19:42
4

ReplaceRepeated (short form //.) uses a depth-first preorder traversal. As an alternative you might consider using a depth-first postorder traversal, as provided by MapAll (short form //@).

Because rm -rf's code goes in the top-down direction he used matching and prepending of multiple integers at once. Half way through the process the list is transformed into this:

{{1, 1}, {2, 2}, {{3, 3, 1}, {3, 3, 2}, {3, 31, {31, 1}, {32, 2}}}}

This may or may not have been your intention. For example, his method will expand {0, 1, {2, 2}, {3, 3}} into {{0, 1, 2, 2}, {0, 1, 3, 3}}. Suppose you didn't want this, and wanted to expand only list starting with a single atom rather than a sequence?

You might then use something like this:

f[{a_?AtomQ, b__List}] := Sequence @@ (Prepend[#, a] & /@ {b})
f[other_] := other

f //@ list
{{1, 1}, {2, 2}, {3, 3, 1}, {3, 3, 2}, {3, 31, 31, 1}, {3, 31, 32, 2}}

And:

list2 = {{1, 1}, {0, 1, {2, 2}}, {3, {3, 1}, {3, 2}, {31, {31, 1}, {32, 2}}}};

f //@ list2
{{1, 1}, {0, 1, {2, 2}}, {3, 3, 1}, {3, 3, 2}, {3, 31, 31, 1}, {3, 31, 32, 2}}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
2

Also:

list = {{1, 1}, {2, 2}, {3, {3, 1}, {3, 2}, {31, {31, 1}, {32, 2}}}};

Cases[Level[list //. {x___Integer, a_Integer,  b__List} :> {x, (Prepend[#, a] & /@ {b})}, Infinity], 
     {__Integer}, {1}]

{{1, 1}, {2, 2}, {3, 3, 1}, {3, 3, 2}, {3, 31, 31, 1}, {3, 31, 32, 2}}

Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453