How can I create an Association from a multidimensional list of values and a list of keys?
Clear[helper];
helper[tl_] := GroupBy[tl, First -> Rest, helper];
helper[{{n_}}] := n;
helper@Transpose@Append[Flatten@vals]@Transpose@Tuples[dims]
The idea is to build a list of paths to each leaf, then use a recursive GroupBy
build the association tree from the list.
Update
I have managed to come up with something faster. But the code becomes more ugly.
Clear[fvals, i, maketree];
fvals = Flatten[vals, Depth[vals] - 3];
maketree[{first_, rest__}] :=
AssociationThread[first -> Table[maketree[{rest}], Length@first]];
maketree[{first_}] := AssociationThread[first, fvals[[i++]]];
i = 1; maketree[dims]
(*<|"New York City" -> <|"Terrace house" -> <|"Two bed" -> <|"2016" ->
0., "2017" -> 633.25|>,
"Three bed" -> <|"2016" -> 642.96, "2017" -> 677.34|>|>,
"Apartment" -> <|"Two bed" -> <|"2016" -> 591.56,
"2017" -> 632.45|>,
"Three bed" -> <|"2016" -> 634.9, "2017" -> 715.6|>|>|>|>*)
I made some timing experiments on code available. (1000 times, repeated timing).
My previous: 0.0665s
My current: 0.019s
Kuba: 0.0400s
andre: 0.0299s
Anton: 0.307s
Assuming vals
has depth corresponding to dims
length:
Module[{i = -2}
, Fold[
Function[{val, dim}, Map[AssociationThread[dim -> #] &, val, {i--}]]
, vals
, Reverse @ dims
]
]
<|"New York City" -> <|"Terrace house" -> <|"Two bed" -> <|"2016" -> 0., "2017" -> 633.25|>, "Three bed" -> <|"2016" -> 642.96, "2017" -> 677.34|>|>, "Apartment" -> <|"Two bed" -> <|"2016" -> 591.56, "2017" -> 632.45|>, "Three bed" -> <|"2016" -> 634.9, "2017" -> 715.6|>|>|>|>
Here is a basic approach without explicit recursion :
vals = {{{{0., 633.25}, {642.96, 677.34}}, {{591.56, 632.45}, {634.9,
715.6}}}}
dims = {{"New York City"}, {"Terrace house", "Apartment"},
{"Two bed", "Three bed"}, {"2016", "2017"}}
MapIndexed[dims[[Length[#2],Last[#2]]]->#1&,vals,{1,-1}] /. x:{_Rule ...} :> Association[x]