# How to replace selected elements of a list of rules with another unbalanced list of rules

I have two lists of rules:

aa = {1 -> {5, 2}, 3 -> {2, 2}, 4 -> {2, 3}, 5 -> {1, 2}, 6 -> {1, 1},
7 -> {2, 1}, 8 -> {1, 1}};
newVnames = {1 -> "EGW", 2 -> "MA2", 3 -> "HLT", 4 -> "AGF",
5 -> "WHS", 6 -> "TSC", 7 -> "CO12", 8 -> "FIN"};


List aa has 7 elements, while newVnames has 8 (unbalanced lists). This implies that we need first to drop one irrelevant rule from newVnames which is 2->"MA2" and then replace the remaining elements in newVnames in ONLY to the first elements (before ->) of aa.

For example, {1->"EGW"} in newVnames should be replaced in the first element of the first element in aa to get:

EGW->{5,2}


I tried various versions of:

Table[aa[[i]][[1]] /. newVnames[[i]], {i, Length[aa]}]


But I could not get what I want to. Please advise me a code for this task.

• Normal@KeyMap[Association[newVnames]]@Association[aa]?
– kglr
Jan 31, 2023 at 18:58
• or Normal@KeyMap[ReplaceAll[newVnames]]@Association[aa]?
– kglr
Jan 31, 2023 at 18:59
• or SubsetMap[ReplaceAll[newVnames], aa, {All, 1}]
– kglr
Jan 31, 2023 at 19:01
• also SubsetMap[ReplaceAll@newVnames, {All, 1}]@aa
– kglr
Jan 31, 2023 at 19:01

Normal @ KeyMap[Association @ newVnames] @ Association @ aa
Normal @ KeyMap[ReplaceAll @ newVnames] @ Association @ aa
MapAt[ReplaceAll @ newVnames, {All, 1}] @ aa
SubsetMap[ReplaceAll @ newVnames, {All, 1}] @ aa


all give

{"EGW" -> {5, 2}, "HLT" -> {2, 2}, "AGF" -> {2, 3}, "WHS" -> {1, 2},
"TSC" -> {1, 1}, "CO12" -> {2, 1}, "FIN" -> {1, 1}}


You can also do in-place replacement using ReplaceAll[newVnames] with ApplyTo:

aa[[All, 1]] //= ReplaceAll[newVnames];
aa

{"EGW" -> {5, 2}, "HLT" -> {2, 2}, "AGF" -> {2, 3}, "WHS" -> {1, 2},
"TSC" -> {1, 1}, "CO12" -> {2, 1}, "FIN" -> {1, 1}}

Replace[aa, newVnames,2]

(* {EGW -> {5, 2}, HLT -> {2, 2}, AGF -> {2, 3}, WHS -> {1, 2}, TSC -> {1, 1},
CO12 -> {2, 1}, FIN -> {1, 1}} *)

• Well now I feel stupid. Very nice. Jan 31, 2023 at 20:44

Maybe the following can help:

 If[Length[#] != 2, Nothing, #[[2, 2]] -> #[[1, 2]]] & /@
GatherBy[Join[aa, newVnames], Keys]
(*{"EGW" -> {5, 2}, "HLT" -> {2, 2}, "AGF" -> {2, 3}, "WHS" -> {1, 2},
"TSC" -> {1, 1}, "CO12" -> {2, 1}, "FIN" -> {1, 1}}*)


I particlarly like @kglr's answers in the comments, but I went down the Merge path:

Values[Merge[KeyIntersection[{newVnames, aa}], Apply[Rule]]]


Using Lookup:

Thread[Values@newVnames ->
Lookup[aa, Keys@newVnames]] // DeleteMissing


OR

MapThread[Rule,
Lookup[KeyIntersection[{newVnames, aa}], #, Nothing] &@
Keys@newVnames]


Result:

{"EGW" -> {5, 2}, "HLT" -> {2, 2}, "AGF" -> {2, 3}, "WHS" -> {1, 2},
"TSC" -> {1, 1}, "CO12" -> {2, 1}, "FIN" -> {1, 1}}

list =
{1 -> {5, 2}, 3 -> {2, 2}, 4 -> {2, 3}, 5 -> {1, 2},
6 -> {1, 1}, 7 -> {2, 1}, 8 -> {1, 1}};

names =
{1 -> "EGW", 2 -> "MA2", 3 -> "HLT", 4 -> "AGF",
5 -> "WHS", 6 -> "TSC", 7 -> "CO12", 8 -> "FIN"};


Using ReplaceAt (new in 13.1)

ReplaceAt[list, names, {All, 1}]


{"EGW" -> {5, 2}, "HLT" -> {2, 2}, "AGF" -> {2, 3}, "WHS" -> {1, 2},
"TSC" -> {1, 1}, "CO12" -> {2, 1}, "FIN" -> {1, 1}}