4
$\begingroup$

I often build nested lists (as a way to keep data sets organised) with some form like:

 nestru = {"a" -> {"x" -> 5, "y" -> 7}, "b" -> {"x" -> 4, "y" -> 6}};

Here "a" and "b" are first order keys that associate a series of second order keys and values with the first order entity. If I want to add a new set of second order rules I can do something like:

 newru = {"z" -> "x"/"y", "xx" -> 2 "x"} /. nestru[[All, 2]]

{{"z" -> 5/7, "xx" -> 10},

{"z" -> 2/3, "xx" -> 8}}

Then I rebuild the whole data structure again:

MapThread[#1 -> #2 &, {nestru[[All, 1]], 
 Flatten[#] & /@ Transpose@{nestru[[All, 2]], newru}}]

{"a" -> {"x" -> 5, "y" -> 7, "z" -> 5/7, "xx" -> 10},

"b" -> {"x" -> 4, "y" -> 6, "z" -> 2/3, "xx" -> 8}}

This feels like a clunky approach. Is there an 'cleaner'/more efficient way to add new sub-rules to a nested list of rules?

$\endgroup$
  • 2
    $\begingroup$ Instead of using nested lists, I would suggest to use nested Associations along with AssociateTo. $\endgroup$ – Henrik Schumacher Nov 26 '18 at 9:35
  • $\begingroup$ @HenrikSchumacher If I convert to Association how do I then use AssociateTo to add values to a 'sub'-Association? It's not clear from the documentation. $\endgroup$ – geordie Nov 26 '18 at 11:10
4
$\begingroup$

Let me show you another way. I'd go with associations and I'd make newgru longer but more robust (here "z", or "xx" could be replaced by rules from nestgru if you are not careful).

data = {"a" -> {"x" -> 5, "y" -> 7}, "b" -> {"x" -> 4, "y" -> 6}} // 
    GeneralUtilities`ToAssociations

<|"a" -> <|"x" -> 5, "y" -> 7|>, "b" -> <|"x" -> 4, "y" -> 6|>|>

<|#, "z" -> #x/#y, "xx" -> 2 #x|> & /@ data

<|"a" -> <|"x" -> 5, "y" -> 7, "z" -> 5/7, "xx" -> 10|>, "b" -> <|"x" -> 4, "y" -> 6, "z" -> 2/3, "xx" -> 8|>|>

$\endgroup$
  • $\begingroup$ It's about time for me to read more about associations... The only problem I see is how to turn it back into a list of rules? If I use Normal only the top level changes to a List. Again It feels like I have to rebuild the data structure if I want utilise lists of rules. $\endgroup$ – geordie Nov 26 '18 at 10:43
  • 3
    $\begingroup$ @geordie don't go back! But if you really need to: data /. Association -> Normal@*Association $\endgroup$ – Kuba Nov 26 '18 at 10:51
  • $\begingroup$ Moving forward, I'll try not to go back (!) but I currently work with large ecosystem built on lists of rules. It may be that I can use most of this will work with Association'ed structures but I'll need to do some testing. For the moment (until I can brush up) 'old school' seems like the safest way to proceed... $\endgroup$ – geordie Nov 26 '18 at 10:58
  • 2
    $\begingroup$ @geordie Just a remark: Associations are essentially hash tables, so -- in contrast to lists -- operations like insert and delete do not need a full copy of the data structure. Thus Association should not only be much more convenient but also much more efficient. However, they come with a certain extra memory cost. You might also find Dataset interesting. $\endgroup$ – Henrik Schumacher Nov 26 '18 at 11:23
  • $\begingroup$ @HenrikSchumacher, about your insert/delete remark, does it hold for Associations not assigned to a symbol? I have always thought that if an expression isn't assigned to a symbol, the Kernel will make a copy on any modification of this expression to provide immutability... $\endgroup$ – Anton.Sakovich Nov 27 '18 at 8:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.