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$
3
  • 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$ Commented Feb 10, 2017 at 9:56
  • 1
    $\begingroup$ Related: (51472) $\endgroup$ Commented Feb 10, 2017 at 10:17
  • $\begingroup$ That's quite an interesting question/answers-set. $\endgroup$ Commented Feb 10, 2017 at 14:42

3 Answers 3

10
$\begingroup$

# and If -less approach:

lst /. a : KeyValuePattern["a" -> n_ /; n > 3] :> <|a, "c" -> True|> 
$\endgroup$
7
  • $\begingroup$ So there is an If-less version after all. Beautiful code. $\endgroup$ Commented Feb 10, 2017 at 10:01
  • 2
    $\begingroup$ @niloderoock Is If-less a primary metric of success here? $\endgroup$ Commented Feb 10, 2017 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$ Commented Feb 10, 2017 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$ Commented Feb 10, 2017 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$ Commented Feb 11, 2017 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$
6
  • $\begingroup$ Yes, me too, too much If though. $\endgroup$ Commented Feb 10, 2017 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$ Commented Feb 10, 2017 at 9:48
  • 1
    $\begingroup$ Right. p.s. don't know if better, but shorter: <|#, "c" -> True|> $\endgroup$ Commented Feb 10, 2017 at 9:48
  • 1
    $\begingroup$ Sorry, I don't. I'd ask WReach if I'd like to know ;) $\endgroup$ Commented Feb 10, 2017 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$ Commented Feb 11, 2017 at 18:41

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.