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

Malaysia to Papua New Guinea by motorcycle?

List of Bhojpuri films

PHP code is not being executed, instead code shows on the page