6
$\begingroup$

I want to replace all items in li1 that are not members of li2 with x. Except does not seem to work well with /. as can be seen in third line of output. Fourth line of output is correct but I used cumbersome code to produce it.

Do you have a more elegant solution?

li1=Transpose[{Range[10],Range[10,1,-1]}]
li2={{4,7},{9,2},{2,9},{5,6}}
li1 /. Except[Alternatives@@li2] -> x
({#,MemberQ[li2,#]}&/@li1)/.{{n_,False}->x,{n_,True}->n}
Clear[li1,li2]

(* {{1,10},{2,9},{3,8},{4,7},{5,6},{6,5},{7,4},{8,3},{9,2},{10,1}} *)
(* {{4,7},{9,2},{2,9},{5,6}} *)
(* x *)
(* {x,{2,9},x,{4,7},{5,6},x,x,x,{9,2},x} *)
$\endgroup$

3 Answers 3

7
$\begingroup$

Something like this, maybe?

Map[If[MemberQ[li2, #], #, x] &, li1]
$\endgroup$
6
$\begingroup$

The reason Except is not working for you is because the entire list li1 also matches that pattern, so everything is simply replaced by x. To fix it, you need to make sure Except matches only what you want. The easiest is to simply use Replace with a level specification of 1:

Replace[li1, Except[Alternatives @@ li2] -> x, 1]
(* {x, {2, 9}, x, {4, 7}, {5, 6}, x, x, x, {9, 2}, x} *)

An alternative is to use the second argument of Except to force it to only match pairs of things (note that this will fail when li1 is itself two elements long):

li1 /. Except[Alternatives @@ li2, {_, _}] -> x
(* {x, {2, 9}, x, {4, 7}, {5, 6}, x, x, x, {9, 2}, x} *)
$\endgroup$
2
$\begingroup$
(li1 /. Thread[
   Rule[Complement[Union[li1, li2], Intersection[li1, li2]], x]])

{x, {2, 9}, x, {4, 7}, {5, 6}, x, x, x, {9, 2}, x}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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