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
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.
Yes, it is a matter of replacement of heads.
– Αλέξανδρος Ζεγγ
Sep 2 at 14:10