# How to update a rule with some new rule?

If I have a rule

oldRule = {a -> 1, b -> 2}


{a->1,b->2}

Then I have a new rule newRule = {a -> 8, c -> 2}.How to use it to update my oldRule?I hope to get

{a->8,b->2,c->2}

Actually I think the Union can implement this target.But it always will choice that small element.I don't know how to control this behavior.

Union[{a -> 8, c -> 2}, oldRule, SameTest -> (SameQ @@ Keys[{##}] &)]


{a -> 1, b -> 2, c -> 2}

Or any elegant workaround can do this?

• Are Associations allowed?
– Kuba
May 7 '17 at 6:52
• @Kuba Do you mean <|a -> 1, b -> 2, c -> 2|>?It's allowed.
– yode
May 7 '17 at 6:58
• @yode If you define the rules as associations, Join[oldRule, newRule] works. May 7 '17 at 7:19
• Related: 5970 May 7 '17 at 7:28
• Here is a general topic about associations: How to organically merge nested associations?
– Kuba
May 7 '17 at 7:47

foo = Normal@*Merge[Last]

foo@{oldRule, newRule}


Even this will do:

Normal @ <|oldRule, newRule|>


How to organically merge nested associations?

Join[newRule,oldRule]


is all you need to ensure that the new rules are used because the first rule is only ever used. If you wanted to eliminate redundant rules then

DeleteDuplicatesBy[Join[newRule, oldRule], #[[1]]&]

DeleteDuplicatesBy[Join[newRule, oldRule], First]


{a->8,c->2,b->2}

Or by Anjan Kumar's comment

Normal[Join[<|oldRule|>, <|newRule|>]]


{a->8,b->2,c->2}

As my test,the solution based on Associations have a better performance

oldRule = Rule @@@ RandomInteger[1000, {200000, 2}];
newRule = Rule @@@ RandomInteger[1000, {200000, 2}];
AbsoluteTiming[Normal[Join[<|oldRule|>, <|newRule|>]];]
AbsoluteTiming[DeleteDuplicatesBy[Join[newRule, oldRule], First];]


changeRuleV4[rules : (_ -> _) ..] :=
Join[FilterRules[#, Except@Alternatives[rules][[All, 1]]], {rules}] &

changeRuleV4[Sequence @@ newRule][oldRule]


{b -> 2, a -> 8, c -> 2}

We can also apply his other functions, which were written for the replacement of a single rule, repeatedly:

changeRule[rules_, rule : (sym_ -> _)] :=
Append[FilterRules[rules, Except[sym]], rule]

changeRules[rules_, new_] := Fold[changeRule, rules, new]

changeRules[oldRule, newRule]


{b -> 2, a -> 8, c -> 2}

These solutions are slow, especially the second one, but I wanted to show the relation between this post and that other Q&A.

you can use Complement instead of Union

(#2~Join~Complement[#1, #2, SameTest -> (SameQ @@ Keys[{##}] &)]) &[oldRule, newRule]

(* {c -> 2, a -> 8, b -> 2} *)