4
$\begingroup$

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.

$\endgroup$

2 Answers 2

4
$\begingroup$
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];
ReplacePart[list1, Thread[xpos -> list2[[xpos]]]]
{a, 3, b, 5, 6, c}
$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$
    – user106860
    May 30, 2021 at 21:48
  • 1
    $\begingroup$ @user106860, you are right; the argument #2 refers to a list in MapIndexed. $\endgroup$
    – kglr
    May 30, 2021 at 21:49
4
$\begingroup$
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} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.