5
$\begingroup$

I have the following list:

l={{a},{a,b},{a,d},{b,d},{a,b,c},{a,d,b}}

I want to replace a,b with x such that I get:

{{a},{x},{a,d},{b,d},{x,c},{x,d}}

So where every there is a,b in elements of the list I need to to be replaced by letter x, I tried Replace and ReplacePart but I can not figure it out.

$\endgroup$
  • 2
    $\begingroup$ Since the last element transforms like {a,d,b} -> {x,d}, does that mean that the order doesn't matter at all in the sublists? For instance, should {a,a,a,d,b,b,b} become {x,x,x,d}? $\endgroup$ – Marius Ladegård Meyer Jul 20 '18 at 15:43
  • $\begingroup$ Order does not matter and yes it can be like {x,x,x,d}. My point is that let us suppose we do not want to use Sort. How the list can be scanned and where ever there is a,b we change it to x. $\endgroup$ – William Jul 20 '18 at 15:45
  • 2
    $\begingroup$ By "order does not matter," I presume {b, a} would also become {x}? $\endgroup$ – JungHwan Min Jul 20 '18 at 15:47
  • $\begingroup$ That's right :) $\endgroup$ – William Jul 20 '18 at 15:52
  • $\begingroup$ What about {a, a, b, d}? do you want {a, d, x} or {d, x} ? $\endgroup$ – rhermans Jul 20 '18 at 16:03
11
$\begingroup$

OrderlessPatternSequence would work:

l //. {OrderlessPatternSequence[a, b, p___]} :> {x, p}

If it is guaranteed that a and b occur at most once per element, then ReplaceAll is sufficient (instead of ReplaceRepeated):

l /. {OrderlessPatternSequence[a, b, p___]} :> {x, p}
$\endgroup$
  • 1
    $\begingroup$ it seems you don't need ReplaceRepeated (ReplaceAll will do). (+1) $\endgroup$ – kglr Jul 20 '18 at 16:01
  • 1
    $\begingroup$ @kglr without ReplaceRepeated, {a, a, b, b} would become {x, a, b}, which I inferred isn't desirable (from the second comment under OP). $\endgroup$ – JungHwan Min Jul 20 '18 at 16:07
  • $\begingroup$ ah, i see. Thanks. $\endgroup$ – kglr Jul 20 '18 at 16:10
  • $\begingroup$ @kglr edited answer to reflect that. $\endgroup$ – JungHwan Min Jul 20 '18 at 16:17
  • 1
    $\begingroup$ If performance is important consider using Replace at levelspec {1}. $\endgroup$ – Mr.Wizard Jul 20 '18 at 19:13
6
$\begingroup$

Something like

l //. {pre___, a, mid___, b, post___} | {pre___, b, mid___, a, post___}  :> {pre, x, mid, post}

should work.

$\endgroup$
5
$\begingroup$

For the case with no repeated elements you can also use SequenceReplace in combination with OrderlessPatternSequence:

SequenceReplace[{OrderlessPatternSequence[a, p___, b]} -> Sequence[x, p]] /@ l

{{a}, {x}, {a, d}, {b, d}, {x, c}, {x, d}}

$\endgroup$
4
$\begingroup$

Given that it's not clear what is wanted for repeated instances, i.e. if for {a, a, b, d} you want {a, d, x} or {d, x}, I offer another kind solution, that works in the second. If there are no repetitions the result is the same, but a bit slower.

repl = If[
   SubsetQ[#, {a, b}]
   , Prepend[Complement[#, {a, b}], x]
   , #] &;

repl /@ l
(* {{a}, {x}, {a, d}, {b, d}, {x, c}, {x, d}} *)
$\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.