5
$\begingroup$

Given the following MWE, where:

lst = {<|"a" -> 1, "b" -> 2|>,
   <|"a" -> 2, "b" -> 2|>,
   <|"a" -> 3, "b" -> 2|>,
   <|"a" -> 4, "b" -> 2|>,
   <|"a" -> 5, "b" -> 2|>};

and the problem is that:

if the value of a is greater than 3 then "c"-> True must be added to the association.

I have the following =working= code

Map[If[#[[1]] > 3, var = #; AssociateTo[var, "c" -> True], #] &, lst]

which yields:

{<|"a" -> 1, "b" -> 2|>, 
<|"a" -> 2, "b" -> 2|>, 
<|"a" -> 3, "b" -> 2|>, 
<|"a" -> 4, "b" -> 2, "c" -> True|>, 
<|"a" -> 5, "b" -> 2, "c" -> True|>}

I prefer If-less programming and the var=# looks so unnecessary.

Is there a more "elegant" solution to this problem?

$\endgroup$
  • 1
    $\begingroup$ It would appear that you can add keys with at least Join, Append, Prepend, <|..., key -> val|>. I guess this was your real question. $\endgroup$ – Szabolcs Feb 10 '17 at 9:56
  • 1
    $\begingroup$ Related: (51472) $\endgroup$ – Mr.Wizard Feb 10 '17 at 10:17
  • $\begingroup$ That's quite an interesting question/answers-set. $\endgroup$ – nilo de roock Feb 10 '17 at 14:42
10
$\begingroup$

# and If -less approach:

lst /. a : KeyValuePattern["a" -> n_ /; n > 3] :> <|a, "c" -> True|>
$\endgroup$
  • $\begingroup$ So there is an If-less version after all. Beautiful code. $\endgroup$ – nilo de roock Feb 10 '17 at 10:01
  • 2
    $\begingroup$ @niloderoock Is If-less a primary metric of success here? $\endgroup$ – Mr.Wizard Feb 10 '17 at 10:05
  • $\begingroup$ I have this hypothesis that IF's are red flags for poor program design: "When the IF's come in, the quality of software starts to deteriorate." $\endgroup$ – nilo de roock Feb 10 '17 at 10:54
  • $\begingroup$ In refactoring code ( i.e. Java ) I aim to remove all IF's which always leads to cleaner design and code with much less LOC. $\endgroup$ – nilo de roock Feb 10 '17 at 11:17
  • $\begingroup$ Accepted. I didn't even know KeyValuePattern. This function will be of help in a few places of my code. $\endgroup$ – nilo de roock Feb 11 '17 at 9:05
7
$\begingroup$

Terse style:

<|#, If[#a > 3, "c" -> True, {}]|> & /@ lst
{
 <|"a" -> 1, "b" -> 2|>,
 <|"a" -> 2, "b" -> 2|>,
 <|"a" -> 3, "b" -> 2|>,
 <|"a" -> 4, "b" -> 2, "c" -> True|>,
 <|"a" -> 5, "b" -> 2, "c" -> True|>
}

For what it's worth version 10.1 does not have KeyValuePattern, but this works:

lst /. x_ /; x["a"] > 3 :> <|x, "c" -> True|>

And just to play with other methods:

<|#, DeleteCases[<|"c" -> #a > 3|>, False]|> & /@ lst
$\endgroup$
6
$\begingroup$

I recommend

If[#a > 3, Append[#, "c" -> True], #] & /@ lst

if you can tolerate a bit of If.

$\endgroup$
  • $\begingroup$ Yes, me too, too much If though. $\endgroup$ – Kuba Feb 10 '17 at 9:46
  • $\begingroup$ @Kuba Well, you gave the Ifless version and there were a few small things to improve in the original that may make the If bearable after all. Consider it an alternative. $\endgroup$ – Szabolcs Feb 10 '17 at 9:48
  • 1
    $\begingroup$ Right. p.s. don't know if better, but shorter: <|#, "c" -> True|> $\endgroup$ – Kuba Feb 10 '17 at 9:48
  • 1
    $\begingroup$ Sorry, I don't. I'd ask WReach if I'd like to know ;) $\endgroup$ – Kuba Feb 10 '17 at 9:53
  • 1
    $\begingroup$ Maybe because it is stronger than Flat. It also flattens List's: Association[a->1, {b->2, Association[c->3]}] gives <|a -> 1, b -> 2, c -> 3|>. $\endgroup$ – Fred Simons Feb 11 '17 at 18:41

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.