Recursively turn expression into nested list

Recursively turn expression into nested list



I've been trying to write a simple function that turns an expression into a nested list. So for example, a+2b+3c becomes a,2,b,3,c. This is what I wrote:


toList[x_] := Module[,
x = List@@x;
For[i=1, i <= Length[x]; i++,
If[x[[i]] != List@@x[[i]], x[[i]] = toList[x[[i]]]]
];
x
]



However, I keep getting errors like "Tag Plus in a+2b+3c is protected" and "a+2b+3c in the part assignment is not symbol." How can I fix what's going wrong?




2 Answers
2



The following does what you want:


Apply[List, a + 2 b + 3 c, All]



This simply applies List to all parts of the expression in one go.


List



Alternatively:


Replace[a + 2 b + 3 c, _[args___] :> args, All]
(* a, 2, b, 3, c *)



The idea here is to replace the head of any expression with List. Note that Replace[…,…,All] is not equivalent to ReplaceAll[…,…] (i.e. …/.…). The former replaces from the inside out, while the latter from the outside in (and ignores parts that have already been touched)


List


Replace[…,…,All]


ReplaceAll[…,…]


…/.…



Your attempt



As to why your attempt doesn't work:


For


i


i


Equal


Unequal


==


!=


a==1


False


SameQ


UnsameQ


===


=!=



Changing only what's necessary in your code yields the following working version:


toList[y_] := Module[
x = y, i,
x = List @@ x;
For[i = 1, i <= Length[x], i++,
If[x[[i]] =!= List @@ x[[i]],
x[[i]] = toList[x[[i]]]
]
];
x
]

toList[a + 2 b + 3 c]
(* a, 2 b, 3 c *)



Further simplifications could be:



Replace the For loop with Do (which does localize the variable)


For


Do


toList[y_] := Module[
x = y,
x = List @@ x;
Do[
If[x[[i]] =!= List @@ x[[i]],
x[[i]] = toList[x[[i]]]
],
i, Length@x
];
x
]



Replace the For/Do loop with Map (the If now needs to return something in both cases, as the output is used):


For


Do


Map


If


toList[y_] := Module[
x = y,
x = List @@ x;
x = Map[
If[# =!= List @@ #,
toList[#],
#
] &,
x
];
x
]



Remove the unnecessary local variable x:


x


toList[y_] := Map[
If[# =!= List @@ #,
toList[#],
#
] &,
List @@ y
]



Move the termination condition for the recursion into the function definition itself using Condition (/;):


Condition


/;


toList[y_] /; y =!= List @@ y := Map[
toList[#] &,
List @@ y
]
toList[y_] := y



Use shorthands for Map (/@):


Map


/@


toList[y_] /; y =!= List @@ y := toList /@ List @@ y
toList[y_] := y



Remove the termination condition completely (it's not needed, as Map/Apply don't do anything on expressions that have "zero length" (i.e. atoms)


Map


Apply


toList[y_] := toList /@ List @@ y





Yes, it is a matter of replacement of heads.
– Αλέξανδρος Ζεγγ
Sep 2 at 14:10





Wow, thanks! That is a really detailed explanation
– user2520385
Sep 2 at 14:22


expr = a + 2 b + 3 (4 E^x + 3 x);

ReplaceRepeated[expr, f_[args___] /; (TrueQ[f =!= List]) :> List[args]]

(* a, 2, b, 3, 4, E, x, 3, x *)



Thanks for contributing an answer to Mathematica Stack Exchange!



But avoid



Use MathJax to format equations. MathJax reference.



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)