# Applying transformation rule for corresponding indices?

I have two lists, that looks like below

list1 = {a, x, b, x, x, c};
list2 = {2, 3, 4, 5, 6, 7};


Any time there is an x in the first list (list1), I want to replace it with the corresponding element in the second list (list2).

Any suggestions on nice ways to go about doing this?

I realize this should be simple with a loop (get the length of the lists, let the loop iterator be the index, and just compare and replace element by element)

However, I believe its usually better to use Map, MapThread, or take advantage of Listable attributes. I don't see how I can do so here, but feel there might be a simple way?

Perhaps something with MapIndexed as mentioned here

Edit: The best way I can come up with is below. It still requires using a local environment Module though, which I feel like might be avoided by a better approach.

Module[{rules, keys},
keys = Flatten@Position[{a, x, b, x, x, c}, x];
rules = AssociationThread[keys -> {2, 3, 4, 5, 6, 7}[[keys]]];
ReplacePart[{a, x, b, x, x, c}, rules]
]


Edit 2: I have realized my question is perhaps a duplicate of this old question, but answers have just been posted here so I will not delete my question. Sorry for the confusion and mistake.

MapIndexed[If[# === x, list2[[#2[[1]]]], #] &, list1]

 {a, 3, b, 5, 6, c}


Alternatively,

xpos = Flatten @ Position[list1, x];
res = list1; res[[xpos]] = list2[[xpos]];  res

 {a, 3, b, 5, 6, c}


and

(Transpose[{list1, list2}] /. {x, i_} :> {i, i})[[All, 1]]

{a, 3, b, 5, 6, c}


and alternative way to use ReplacePart:

xpos = Flatten @ Position[list1, x];

{a, 3, b, 5, 6, c}

• I like the first one since it does not require defining a new (possibly local) variable. The reason you have #2[[1]] though, is because I think MapIndexed uses the index in brackets as the second argument, yes? (i.e. it uses {i} instead of i). I see you have also edited to add more solutions, some of which also may not need local variables. Thank you. May 30, 2021 at 21:48
• @user106860, you are right; the argument #2 refers to a list in MapIndexed.
– kglr
May 30, 2021 at 21:49
list1 = {a, x, b, x, x, c};
list2 = {2, 3, 4, 5, 6, 7};


Find the positions of the first list

ix = Position[list1, x]
(* {{2}, {4}, {5}} *)


Replace them in the second list

ReplacePart[list1, Thread[ix -> Extract[list2, ix]]]
(* {a, 3, b, 5, 6, c} *)