8
$\begingroup$

Consider I have the following list with no duplicates. I would like to replace {a,c} with a number.

lst = {a,b,c,d}

Result I want is {1, b, d}. This can be in any order.


I have tried the following using SequenceReplace[] which works only if the sequence I want to replace is in the same order as in lst.

SequenceReplace[{a, b, c, d}, {b, c} -> 1]

{a,1,d}

SequenceReplace[{a, b, c, d}, {a, c} -> 1]

{a,b,c,d}

Is there a way to get {1, b, d}?

$\endgroup$
6
  • $\begingroup$ Do you have more than one occurrence of a, ... , c, ... in your input list? If so then please update the question with more test cases. $\endgroup$
    – Syed
    Commented Mar 25, 2022 at 16:18
  • 5
    $\begingroup$ You cold replace a with 1 and c with Nothing: lst /. {a -> 1, c -> Nothing} $\endgroup$ Commented Mar 25, 2022 at 16:26
  • $\begingroup$ @Syed the list doesn't have any duplicates. I have updated the question $\endgroup$ Commented Mar 25, 2022 at 16:31
  • 1
    $\begingroup$ If you do require to work with non-adjacent sequence items, here is a possible solution: SequenceReplace[lst, {g___, a, x___, c, y___} :> Sequence[g, 1, x, y]] $\endgroup$
    – Syed
    Commented Mar 25, 2022 at 16:35
  • 1
    $\begingroup$ or just SequenceReplace[lst, {a, x___, c} -> Sequence[1, x]] $\endgroup$
    – Roman
    Commented Mar 25, 2022 at 16:41

5 Answers 5

10
$\begingroup$

You may use OrderlessPatternSequence.

With

lst = Permutations[{a, b, c, d}]
{{a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b}
,{b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a}
,{c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a}
,{d,a,b,c},{d,a,c,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a}}

Then

lst /. {OrderlessPatternSequence[a, c, e___]} :> {1, e}
{{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d}
,{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d}
,{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d}
,{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d},{1,b,d}}

Hope this helps.

$\endgroup$
2
  • 2
    $\begingroup$ Since the pattern is orderless you don't need separate s,m,e. Just lst /. {OrderlessPatternSequence[a, c, x___]} :> {1, x} $\endgroup$ Commented Mar 25, 2022 at 19:25
  • $\begingroup$ @SimonWoods Yes, you are correct. $\endgroup$
    – Edmund
    Commented Mar 25, 2022 at 20:02
5
$\begingroup$
$Version

(* "13.0.1 for Mac OS X x86 (64-bit) (January 28, 2022)" *)

Clear["Global`*"]

rules[lst_, target_, value_] := 
 Flatten[{#[[1]] :> value, Thread[Rest[#] :> Nothing]}] &@
  Select[lst, MemberQ[target, #] &]

lst = {a, b, c, d};

target = {a, c};

lst /. rules[lst, target, 1]

(* {1, b, d} )

For a more complicated example

SeedRandom[1234];

lst = RandomSample[{a, b, c, d, e, f}]

(* {a, f, d, b, e, c} *)

target = {c, a, f};

lst /. rules[lst, target, 1]

(* {1, d, b, e} *)
$\endgroup$
2
$\begingroup$
list = {a, b, c, d};

f = SequenceReplace[list, {OrderlessPatternSequence[#1, #2, x_]} :> Sequence[1, x]] &;

f @@@ {{a, c}, {b, d}, {a, b}}

{{1, b, d}, {a, 1, c}, {1, c, d}}

$\endgroup$
2
$\begingroup$
lst = {a, b, c, d};    

Using MapAt and DeleteElements:

rules[lst_, target_, value_] := 
Reverse@DeleteElements[Reverse@MapAt[value &, lst, 
Position[lst, Alternatives @@ target]], {value} -> {value}]

rules[lst, #, 1] & /@ {{a, c}, {b, d}, {a, b}}

{{1, b, d}, {a, 1, c}, {1, c, d}}

$\endgroup$
1
$\begingroup$

A basic approach:

func[s_, t_] := 
 If[Intersection[s, t] == Sort[t], 
  Join[SymmetricDifference[s, t], {1}], s]

For example:

w = {a, b, c, d};
func[w, {a, c}]

yields {b, d, 1}

Or @BobHanlon example:

SeedRandom[1234];
lst = RandomSample[{a, b, c, d, e, f}]
func[lst, {c, a, f}]

yields: {b, d, e, 1}

$\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.