How to invert MapIndexed on a ragged structure? How to construct a tree from rules?
$begingroup$
I have an arbitrary ragged nested list-of-lists (a tree) like
A = {{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n};
Its structure is given by the rules
B = Flatten[MapIndexed[#2 -> #1 &, A, {-1}]]
{{1, 1} -> a, {1, 2} -> b, {2, 1} -> c, {2, 2} -> d, {3, 1, 1, 1} -> e, {3, 1, 1, 2} -> f, {3, 1, 1, 3} -> g, {3, 1, 1, 4} -> h, {3, 1, 1, 5} -> i, {3, 1, 2, 1} -> j, {3, 1, 2, 2} -> k, {3, 1, 2, 3} -> l, {3, 2} -> m, {4} -> n}
How can I invert this operation? How can I construct A
solely from the information given in B
?
Edit: additional requirements
Thanks to all for contributing so far!
For robustness and versatility it would be nice for a solution to accept incomplete input like B = {{2} -> 1}
and still generate {0,1}
, not just {1}
.
Also, there are some very deep trees to be constructed, like B = {ConstantArray[2, 100] -> 1}
. A certain parsimony is required to be able to construct such trees within reasonable time.
list-manipulation data-structures trees
$endgroup$
add a comment |
$begingroup$
I have an arbitrary ragged nested list-of-lists (a tree) like
A = {{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n};
Its structure is given by the rules
B = Flatten[MapIndexed[#2 -> #1 &, A, {-1}]]
{{1, 1} -> a, {1, 2} -> b, {2, 1} -> c, {2, 2} -> d, {3, 1, 1, 1} -> e, {3, 1, 1, 2} -> f, {3, 1, 1, 3} -> g, {3, 1, 1, 4} -> h, {3, 1, 1, 5} -> i, {3, 1, 2, 1} -> j, {3, 1, 2, 2} -> k, {3, 1, 2, 3} -> l, {3, 2} -> m, {4} -> n}
How can I invert this operation? How can I construct A
solely from the information given in B
?
Edit: additional requirements
Thanks to all for contributing so far!
For robustness and versatility it would be nice for a solution to accept incomplete input like B = {{2} -> 1}
and still generate {0,1}
, not just {1}
.
Also, there are some very deep trees to be constructed, like B = {ConstantArray[2, 100] -> 1}
. A certain parsimony is required to be able to construct such trees within reasonable time.
list-manipulation data-structures trees
$endgroup$
add a comment |
$begingroup$
I have an arbitrary ragged nested list-of-lists (a tree) like
A = {{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n};
Its structure is given by the rules
B = Flatten[MapIndexed[#2 -> #1 &, A, {-1}]]
{{1, 1} -> a, {1, 2} -> b, {2, 1} -> c, {2, 2} -> d, {3, 1, 1, 1} -> e, {3, 1, 1, 2} -> f, {3, 1, 1, 3} -> g, {3, 1, 1, 4} -> h, {3, 1, 1, 5} -> i, {3, 1, 2, 1} -> j, {3, 1, 2, 2} -> k, {3, 1, 2, 3} -> l, {3, 2} -> m, {4} -> n}
How can I invert this operation? How can I construct A
solely from the information given in B
?
Edit: additional requirements
Thanks to all for contributing so far!
For robustness and versatility it would be nice for a solution to accept incomplete input like B = {{2} -> 1}
and still generate {0,1}
, not just {1}
.
Also, there are some very deep trees to be constructed, like B = {ConstantArray[2, 100] -> 1}
. A certain parsimony is required to be able to construct such trees within reasonable time.
list-manipulation data-structures trees
$endgroup$
I have an arbitrary ragged nested list-of-lists (a tree) like
A = {{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n};
Its structure is given by the rules
B = Flatten[MapIndexed[#2 -> #1 &, A, {-1}]]
{{1, 1} -> a, {1, 2} -> b, {2, 1} -> c, {2, 2} -> d, {3, 1, 1, 1} -> e, {3, 1, 1, 2} -> f, {3, 1, 1, 3} -> g, {3, 1, 1, 4} -> h, {3, 1, 1, 5} -> i, {3, 1, 2, 1} -> j, {3, 1, 2, 2} -> k, {3, 1, 2, 3} -> l, {3, 2} -> m, {4} -> n}
How can I invert this operation? How can I construct A
solely from the information given in B
?
Edit: additional requirements
Thanks to all for contributing so far!
For robustness and versatility it would be nice for a solution to accept incomplete input like B = {{2} -> 1}
and still generate {0,1}
, not just {1}
.
Also, there are some very deep trees to be constructed, like B = {ConstantArray[2, 100] -> 1}
. A certain parsimony is required to be able to construct such trees within reasonable time.
list-manipulation data-structures trees
list-manipulation data-structures trees
edited yesterday
Roman
asked Mar 29 at 21:15
RomanRoman
4,1151027
4,1151027
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
$begingroup$
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}
$endgroup$
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use ofValues
makes a lot of assumptions about the listB
. Better to define something likesortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same withgroupMe[B]
andgroupMe[Reverse[B]]
etc.
$endgroup$
– Roman
2 days ago
$begingroup$
RecursiveGroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
$begingroup$
What does theBlock[{Nothing}, ...]
wrapper do?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array ofNothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.
$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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?
$endgroup$
add a comment |
$begingroup$
Here's a convoluted way using pattern replacements:
DeleteCases[
With[{m = Max[Length /@ Keys[B]]},
Array[
List,
Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]
] /.
Map[
Fold[
Insert[
{#, ___},
_,
Append[ConstantArray[1, #2], -1]] &,
#[[1]],
Range[m - Length[#[[1]]]]
] -> #[[2]] &,
B
]
],
{__Integer},
Infinity
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
$endgroup$
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
Here is a more functional (but memory-inefficient) version where no temporary variables are used. In the meantime the readability is "manageable". It works mostly like b3m2a1's this answer.
First a helper function branch
:
branch = Through@*{##}&
The main function ruleRevert
is defined as the following:
ruleRevert = RightComposition[
branch[
ReplacePart
, (* make a rectangular array compatible with B: *)
RightComposition[
Keys
, (* find max size of each level: *)
MapIndexed[#2[[2]] -> #1 &, #, {-1}] &, Merge[Max], KeySort, Values
, (* make rectangular array : *)
ConstantArray[Inactive[Sequence], #] &
]
]
, (* replace elements in rect-array with corresponding elements in B: *)
Apply @ Construct
, (* remove extra Inactive[Sequence] : *)
Activate
]
It's easy to verify
ruleRevert[B] == A
(* True *)
$endgroup$
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, forruleRevert[{{2}->1}]
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't{0,1}
be corresponding to{{1}->0,{2}->1}
(throughFlatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do haveruleRevert[{{1}->0,{2}->1}] == {0,1}
..
$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing{1, 1} -> a
inB
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something likeReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)
$endgroup$
– Silvia
2 days ago
add a comment |
$begingroup$
This
toTree[l_]:=Quiet[GatherBy[Keys[l],Table[With[{i=i},Function[Part[Slot[1],i]]],
{i,Max[Length/@Keys[l]]}]]/.l//.List[x_]->x]
seems to meet OP's requirements, and has passed a tiny battery of tests. Wrapping the rhs in Quiet
suppresses some complaints that Part
makes when digging too deeply into the leaves of the tree.
$endgroup$
$begingroup$
Hi Mark, your solution doesn't work onA={0}
andB={{1}->0}
: ontoTree[B]
it returns0
.
$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
add a comment |
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
});
});
}, "mathjax-editing");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "387"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f194217%2fhow-to-invert-mapindexed-on-a-ragged-structure-how-to-construct-a-tree-from-rul%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
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}
$endgroup$
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use ofValues
makes a lot of assumptions about the listB
. Better to define something likesortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same withgroupMe[B]
andgroupMe[Reverse[B]]
etc.
$endgroup$
– Roman
2 days ago
$begingroup$
RecursiveGroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use ofValues
makes a lot of assumptions about the listB
. Better to define something likesortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same withgroupMe[B]
andgroupMe[Reverse[B]]
etc.
$endgroup$
– Roman
2 days ago
$begingroup$
RecursiveGroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
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}
answered Mar 29 at 21:28
b3m2a1b3m2a1
28.5k359164
28.5k359164
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use ofValues
makes a lot of assumptions about the listB
. Better to define something likesortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same withgroupMe[B]
andgroupMe[Reverse[B]]
etc.
$endgroup$
– Roman
2 days ago
$begingroup$
RecursiveGroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use ofValues
makes a lot of assumptions about the listB
. Better to define something likesortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same withgroupMe[B]
andgroupMe[Reverse[B]]
etc.
$endgroup$
– Roman
2 days ago
$begingroup$
RecursiveGroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!
$endgroup$
– Roman
2 days ago
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Thanks for your efforts, b3m2a1! Your solutions of course all work, and this one I find the most appealing because of its parsimonious recursive nature. Cheers!
$endgroup$
– Roman
2 days ago
$begingroup$
Your use of
Values
makes a lot of assumptions about the list B
. Better to define something like sortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same with groupMe[B]
and groupMe[Reverse[B]]
etc.$endgroup$
– Roman
2 days ago
$begingroup$
Your use of
Values
makes a lot of assumptions about the list B
. Better to define something like sortedvalues[a_Association] := Lookup[a, Range[Max[Keys[a]]], Null]
. Like this you get the same with groupMe[B]
and groupMe[Reverse[B]]
etc.$endgroup$
– Roman
2 days ago
$begingroup$
Recursive
GroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!$endgroup$
– Roman
2 days ago
$begingroup$
Recursive
GroupBy
must be the most powerful structural operator I've come across so far. Thanks for enlightening us on its use!$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
$begingroup$
What does theBlock[{Nothing}, ...]
wrapper do?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array ofNothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.
$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
$begingroup$
What does theBlock[{Nothing}, ...]
wrapper do?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array ofNothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.
$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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}
$endgroup$
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}
answered Mar 29 at 21:39
b3m2a1b3m2a1
28.5k359164
28.5k359164
$begingroup$
What does theBlock[{Nothing}, ...]
wrapper do?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array ofNothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.
$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
What does theBlock[{Nothing}, ...]
wrapper do?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array ofNothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.
$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
What does the
Block[{Nothing}, ...]
wrapper do?$endgroup$
– Roman
2 days ago
$begingroup$
What does the
Block[{Nothing}, ...]
wrapper do?$endgroup$
– Roman
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array of
Nothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.$endgroup$
– b3m2a1
2 days ago
$begingroup$
@Roman haven’t tested I’d it’d work without it but usually making an array of
Nothing
should become a bunch of empty lists so I figured I’d block that behavior while assigning parts.$endgroup$
– b3m2a1
2 days ago
$begingroup$
This solution does not fill in blanks, that is, for
B={{2}->1}
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
$begingroup$
This solution does not fill in blanks, that is, for
B={{2}->1}
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
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?
$endgroup$
add a comment |
$begingroup$
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?
$endgroup$
add a comment |
$begingroup$
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?
$endgroup$
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?
edited yesterday
answered 2 days ago
RomanRoman
4,1151027
4,1151027
add a comment |
add a comment |
$begingroup$
Here's a convoluted way using pattern replacements:
DeleteCases[
With[{m = Max[Length /@ Keys[B]]},
Array[
List,
Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]
] /.
Map[
Fold[
Insert[
{#, ___},
_,
Append[ConstantArray[1, #2], -1]] &,
#[[1]],
Range[m - Length[#[[1]]]]
] -> #[[2]] &,
B
]
],
{__Integer},
Infinity
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
$endgroup$
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
Here's a convoluted way using pattern replacements:
DeleteCases[
With[{m = Max[Length /@ Keys[B]]},
Array[
List,
Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]
] /.
Map[
Fold[
Insert[
{#, ___},
_,
Append[ConstantArray[1, #2], -1]] &,
#[[1]],
Range[m - Length[#[[1]]]]
] -> #[[2]] &,
B
]
],
{__Integer},
Infinity
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
$endgroup$
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
Here's a convoluted way using pattern replacements:
DeleteCases[
With[{m = Max[Length /@ Keys[B]]},
Array[
List,
Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]
] /.
Map[
Fold[
Insert[
{#, ___},
_,
Append[ConstantArray[1, #2], -1]] &,
#[[1]],
Range[m - Length[#[[1]]]]
] -> #[[2]] &,
B
]
],
{__Integer},
Infinity
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
$endgroup$
Here's a convoluted way using pattern replacements:
DeleteCases[
With[{m = Max[Length /@ Keys[B]]},
Array[
List,
Max /@ Transpose[PadRight[#, m] & /@ Keys[B]]
] /.
Map[
Fold[
Insert[
{#, ___},
_,
Append[ConstantArray[1, #2], -1]] &,
#[[1]],
Range[m - Length[#[[1]]]]
] -> #[[2]] &,
B
]
],
{__Integer},
Infinity
]
{{a, b}, {c, d}, {{{e, f, g, h, i}, {j, k, l}}, m}, n}
answered Mar 29 at 21:38
b3m2a1b3m2a1
28.5k359164
28.5k359164
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
This solution does not fill in blanks, that is, forB={{2}->1}
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
This solution does not fill in blanks, that is, for
B={{2}->1}
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
$begingroup$
This solution does not fill in blanks, that is, for
B={{2}->1}
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
add a comment |
$begingroup$
Here is a more functional (but memory-inefficient) version where no temporary variables are used. In the meantime the readability is "manageable". It works mostly like b3m2a1's this answer.
First a helper function branch
:
branch = Through@*{##}&
The main function ruleRevert
is defined as the following:
ruleRevert = RightComposition[
branch[
ReplacePart
, (* make a rectangular array compatible with B: *)
RightComposition[
Keys
, (* find max size of each level: *)
MapIndexed[#2[[2]] -> #1 &, #, {-1}] &, Merge[Max], KeySort, Values
, (* make rectangular array : *)
ConstantArray[Inactive[Sequence], #] &
]
]
, (* replace elements in rect-array with corresponding elements in B: *)
Apply @ Construct
, (* remove extra Inactive[Sequence] : *)
Activate
]
It's easy to verify
ruleRevert[B] == A
(* True *)
$endgroup$
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, forruleRevert[{{2}->1}]
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't{0,1}
be corresponding to{{1}->0,{2}->1}
(throughFlatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do haveruleRevert[{{1}->0,{2}->1}] == {0,1}
..
$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing{1, 1} -> a
inB
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something likeReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)
$endgroup$
– Silvia
2 days ago
add a comment |
$begingroup$
Here is a more functional (but memory-inefficient) version where no temporary variables are used. In the meantime the readability is "manageable". It works mostly like b3m2a1's this answer.
First a helper function branch
:
branch = Through@*{##}&
The main function ruleRevert
is defined as the following:
ruleRevert = RightComposition[
branch[
ReplacePart
, (* make a rectangular array compatible with B: *)
RightComposition[
Keys
, (* find max size of each level: *)
MapIndexed[#2[[2]] -> #1 &, #, {-1}] &, Merge[Max], KeySort, Values
, (* make rectangular array : *)
ConstantArray[Inactive[Sequence], #] &
]
]
, (* replace elements in rect-array with corresponding elements in B: *)
Apply @ Construct
, (* remove extra Inactive[Sequence] : *)
Activate
]
It's easy to verify
ruleRevert[B] == A
(* True *)
$endgroup$
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, forruleRevert[{{2}->1}]
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't{0,1}
be corresponding to{{1}->0,{2}->1}
(throughFlatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do haveruleRevert[{{1}->0,{2}->1}] == {0,1}
..
$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing{1, 1} -> a
inB
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something likeReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)
$endgroup$
– Silvia
2 days ago
add a comment |
$begingroup$
Here is a more functional (but memory-inefficient) version where no temporary variables are used. In the meantime the readability is "manageable". It works mostly like b3m2a1's this answer.
First a helper function branch
:
branch = Through@*{##}&
The main function ruleRevert
is defined as the following:
ruleRevert = RightComposition[
branch[
ReplacePart
, (* make a rectangular array compatible with B: *)
RightComposition[
Keys
, (* find max size of each level: *)
MapIndexed[#2[[2]] -> #1 &, #, {-1}] &, Merge[Max], KeySort, Values
, (* make rectangular array : *)
ConstantArray[Inactive[Sequence], #] &
]
]
, (* replace elements in rect-array with corresponding elements in B: *)
Apply @ Construct
, (* remove extra Inactive[Sequence] : *)
Activate
]
It's easy to verify
ruleRevert[B] == A
(* True *)
$endgroup$
Here is a more functional (but memory-inefficient) version where no temporary variables are used. In the meantime the readability is "manageable". It works mostly like b3m2a1's this answer.
First a helper function branch
:
branch = Through@*{##}&
The main function ruleRevert
is defined as the following:
ruleRevert = RightComposition[
branch[
ReplacePart
, (* make a rectangular array compatible with B: *)
RightComposition[
Keys
, (* find max size of each level: *)
MapIndexed[#2[[2]] -> #1 &, #, {-1}] &, Merge[Max], KeySort, Values
, (* make rectangular array : *)
ConstantArray[Inactive[Sequence], #] &
]
]
, (* replace elements in rect-array with corresponding elements in B: *)
Apply @ Construct
, (* remove extra Inactive[Sequence] : *)
Activate
]
It's easy to verify
ruleRevert[B] == A
(* True *)
edited 2 days ago
answered 2 days ago
SilviaSilvia
23k269132
23k269132
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, forruleRevert[{{2}->1}]
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't{0,1}
be corresponding to{{1}->0,{2}->1}
(throughFlatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do haveruleRevert[{{1}->0,{2}->1}] == {0,1}
..
$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing{1, 1} -> a
inB
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something likeReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)
$endgroup$
– Silvia
2 days ago
add a comment |
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, forruleRevert[{{2}->1}]
it returns{1}
instead of{0,1}
. Is there a way to fix this?
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't{0,1}
be corresponding to{{1}->0,{2}->1}
(throughFlatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do haveruleRevert[{{1}->0,{2}->1}] == {0,1}
..
$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing{1, 1} -> a
inB
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something likeReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)
$endgroup$
– Silvia
2 days ago
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, for
ruleRevert[{{2}->1}]
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
$begingroup$
Thanks Silvia! Your solution does not fill in blanks, that is, for
ruleRevert[{{2}->1}]
it returns {1}
instead of {0,1}
. Is there a way to fix this?$endgroup$
– Roman
2 days ago
$begingroup$
@Roman Good point. But shouldn't
{0,1}
be corresponding to {{1}->0,{2}->1}
(through Flatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do have ruleRevert[{{1}->0,{2}->1}] == {0,1}
..$endgroup$
– Silvia
2 days ago
$begingroup$
@Roman Good point. But shouldn't
{0,1}
be corresponding to {{1}->0,{2}->1}
(through Flatten[MapIndexed[#2->#1&,{0,1},{-1}]]
)? In that case we do have ruleRevert[{{1}->0,{2}->1}] == {0,1}
..$endgroup$
– Silvia
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
I agree with you. The idea is to add a bit of flexibility and fault tolerance.
$endgroup$
– Roman
2 days ago
$begingroup$
@Roman I tried removing
{1, 1} -> a
in B
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something like ReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)$endgroup$
– Silvia
2 days ago
$begingroup$
@Roman I tried removing
{1, 1} -> a
in B
from your question. I think the main issue here is that it's hard to tell the shape/depth of the unspecified part. But if we restrict it to the most shallow level, something like ReplaceRepeated
with proper pattern should do the trick. (It's very late here, maybe I shall review it tomorrow.)$endgroup$
– Silvia
2 days ago
add a comment |
$begingroup$
This
toTree[l_]:=Quiet[GatherBy[Keys[l],Table[With[{i=i},Function[Part[Slot[1],i]]],
{i,Max[Length/@Keys[l]]}]]/.l//.List[x_]->x]
seems to meet OP's requirements, and has passed a tiny battery of tests. Wrapping the rhs in Quiet
suppresses some complaints that Part
makes when digging too deeply into the leaves of the tree.
$endgroup$
$begingroup$
Hi Mark, your solution doesn't work onA={0}
andB={{1}->0}
: ontoTree[B]
it returns0
.
$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
add a comment |
$begingroup$
This
toTree[l_]:=Quiet[GatherBy[Keys[l],Table[With[{i=i},Function[Part[Slot[1],i]]],
{i,Max[Length/@Keys[l]]}]]/.l//.List[x_]->x]
seems to meet OP's requirements, and has passed a tiny battery of tests. Wrapping the rhs in Quiet
suppresses some complaints that Part
makes when digging too deeply into the leaves of the tree.
$endgroup$
$begingroup$
Hi Mark, your solution doesn't work onA={0}
andB={{1}->0}
: ontoTree[B]
it returns0
.
$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
add a comment |
$begingroup$
This
toTree[l_]:=Quiet[GatherBy[Keys[l],Table[With[{i=i},Function[Part[Slot[1],i]]],
{i,Max[Length/@Keys[l]]}]]/.l//.List[x_]->x]
seems to meet OP's requirements, and has passed a tiny battery of tests. Wrapping the rhs in Quiet
suppresses some complaints that Part
makes when digging too deeply into the leaves of the tree.
$endgroup$
This
toTree[l_]:=Quiet[GatherBy[Keys[l],Table[With[{i=i},Function[Part[Slot[1],i]]],
{i,Max[Length/@Keys[l]]}]]/.l//.List[x_]->x]
seems to meet OP's requirements, and has passed a tiny battery of tests. Wrapping the rhs in Quiet
suppresses some complaints that Part
makes when digging too deeply into the leaves of the tree.
answered 2 days ago
High Performance MarkHigh Performance Mark
636512
636512
$begingroup$
Hi Mark, your solution doesn't work onA={0}
andB={{1}->0}
: ontoTree[B]
it returns0
.
$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
add a comment |
$begingroup$
Hi Mark, your solution doesn't work onA={0}
andB={{1}->0}
: ontoTree[B]
it returns0
.
$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
$begingroup$
Hi Mark, your solution doesn't work on
A={0}
and B={{1}->0}
: on toTree[B]
it returns 0
.$endgroup$
– Roman
2 days ago
$begingroup$
Hi Mark, your solution doesn't work on
A={0}
and B={{1}->0}
: on toTree[B]
it returns 0
.$endgroup$
– Roman
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
$begingroup$
Well, I'm not terribly surprised, I only gave it a few tests. If I have any more time to waste ( :-) ) on this I'll have another look.
$endgroup$
– High Performance Mark
2 days ago
add a comment |
Thanks for contributing an answer to Mathematica Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f194217%2fhow-to-invert-mapindexed-on-a-ragged-structure-how-to-construct-a-tree-from-rul%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown