It's a little on the hairy side, but you can do it functionally (i.e., without mutating a counter) by first finding all the leaves using Position
, and then replacing what you find at those positions one by one using Fold
:
tree = {a, b, {c, d}, e, {f, {g, h}}};
Module[{indexLeaf},
With[{indexedPositions = Transpose[
{Range@Length@#, #}] &@Position[tree, _, {-1}, Heads -> False]},
indexLeaf[tree_, {index_, position_}] :=
MapAt[{index, #} &, tree, position];
Fold[indexLeaf, tree, indexedPositions]]]
{{1, a}, {2, b}, {{3, c}, {4, d}}, {5, e}, {{6, f}, {{7, g}, {8, h}}}}
EDIT to add:
There's an alternative solution that may be a litle cleaner. It uses ReplacePart
to make all the changes in one swell foop instead of relying on the ugly Fold
/MapAt
combo. Factoring things a bit:
ClearAll[indexedLeafPositions, indexedLeafRules, indexLeaves];
indexedLeafPositions[tree_] :=
Transpose[{#, Range@Length@#}] &@
Position[tree, _, {-1}, Heads -> False];
indexedLeafRules[tree_] :=
Cases[indexedLeafPositions@tree,
{pos_, n_} :> (pos -> {n, Extract[tree, pos]})];
indexLeaves[tree_] :=
ReplacePart[tree, indexedLeafRules@tree];
Trying it out:
indexLeaves[tree]
{{1, a}, {2, b}, {{3, c}, {4, d}}, {5, e}, {{6, f}, {{7, g}, {8, h}}}}
ReplaceAll
. $\endgroup${{a**x},b}
to be replaced with{{{1,a**x}},{2, b}}
or{{{1, a}**{2, x}},{3,b}}
? You should note that the answers given will not all do the same thing for cases like that. I'd expect this could bite you once using it in practice... $\endgroup$