4

I want to create a List of Associations from data in a two-dimensional List by using ReplaceAll, but did not manage to produce the expected result.

So here is a short example, the original lists are stored in the variable values:

values = {{1, a}, {2, b}, {3, c}}
{{1, a}, {2, b}, {3, c}}

and I want to transform this to a List of Associations with Keys "N" and "C" for the numbers and the characters

{<|"N" -> 1, "C" -> a|>, <|"N" -> 2, "C" -> b|>, <|"N" -> 3, "C" -> c|>}

If I use the ReplaceAll command to create an Association I do not get the desired result

values /. {num_, char_} -> <|"N" -> num, "C" -> char|>
{<|"N" -> num, "C" -> char|>, <|"N" -> num, "C" -> char|>, <|"N" -> num, "C" -> char|>}

So the values for num and char are not considered correctly in ReplaceAll. However, If I would replace the Association by a List of Rules this works:

values /. {num_, char_} -> {"N" -> num, "C" -> char}
{{"N" -> 1, "C" -> a}, {"N" -> 2, "C" -> b}, {"N" -> 3, "C" -> c}}

Is there any explanation why the behaviour is different for the Association? What is the usual way to create Associations from Lists?

Mathias
  • 619
  • 3
  • 9
  • Okay, I just found out that using :> (RuleDelayed) instead of -> (Rule) in ReplaceAll does the trick. Is there any explanation why? So the working command is values /. {num_, char_} :> <|"N" -> num, "C" -> char|> – Mathias Jan 21 '22 at 13:29

1 Answers1

8

If you use "Rule" the right side is evaluated at once resulting in:

{<|"N" -> num, "C" -> char|>, <|"N" -> num, "C" -> char|>, <|"N" -> num, "C" -> char|>}

On the other hand, if you use RuleDelayed, the right side is only evaluated when the pattern has matched:

values = {{1, a}, {2, b}, {3, c}};
values /. {num_, char_} :> <|"N" -> num, "C" -> char|>
(*{<|"N" -> 1, "C" -> a|>, <|"N" -> 2, "C" -> b|>, <|"N" -> 3, "C" -> c|>} *)
rcollyer
  • 33,976
  • 7
  • 92
  • 191
Daniel Huber
  • 51,463
  • 1
  • 23
  • 57