How to invert MapIndexed on a ragged structure? How to construct a tree from rules?
Here's a procedural way:
Block[
{Nothing},
Module[
{m = Max[Length /@ Keys[B]], arr},
arr = ConstantArray[Nothing, Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]];
Map[Function[arr[[Sequence @@ #[[1]]]] = #[[2]]], B];
arr
]
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
Here's an inefficient but reasonably simple way:
groupMe[rules_] :=
If[Head[rules[[1]]] === Rule,
Values@GroupBy[
rules,
(#[[1, 1]] &) ->
(If[Length[#[[1]]] === 1, #[[2]], #[[1, 2 ;;]] -> #[[2]]] &),
groupMe
],
rules[[1]]
]
groupMe[B]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
Here is a completed and cleaned-up version of b3m2a1's recursive solution based on the powerful GroupBy
operator:
PositiveIntegerQ[x_] := IntegerQ[x] && Positive[x]
ruleFirst[L_ /; VectorQ[L, PositiveIntegerQ] -> _] := First[L]
ruleFirst[i_?PositiveIntegerQ -> _] := i
ruleRest[(_?PositiveIntegerQ | {_?PositiveIntegerQ}) -> c_] := c
ruleRest[L_ /; VectorQ[L, PositiveIntegerQ] -> c_] := Rest[L] -> c
sortedValues[a_Association] := Lookup[a, Range[Max[Keys[a]]], 0]
toTree[rules : {___, _Rule, ___}] :=
sortedValues@GroupBy[Cases[rules, _Rule], ruleFirst -> ruleRest, toTree]
toTree[rule_Rule] := toTree[{rule}]
toTree[c_List] := Last[c]
toTree[c_] := c
toTree[] = toTree[{}] = {};
This solution mirrors many of SparseArray
's capabilities, like setting unmentioned (but necessary) elements to zero:
toTree[5 -> 1]
{0, 0, 0, 0, 1}
It also cleans up conflicting entries, only keeping the deepest one, or the last one if there are equivalent entries:
toTree[{1 -> 1, 1 -> 2}]
{2}
toTree[{{1, 2} -> 3, 1 -> 1}]
{{0, 3}}
Unlike the solutions that work by selective pruning a huge high-rank tensor, this solution only constructs what is needed. For this reason it can work out situations like
toTree[ConstantArray[2, 100] -> 1]
{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,{0,1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
Can you think of any other edge cases that need to be considered?