This seems simple:
Given
lis = {"abcd12efcdef"}
I would like to delete all instances of "ef" when it directly follows a digit character, to give:
res = {"abcd12cdef"}
Using a regular expression with positive look-behind:
s = "abcd12efcdef";
StringDelete[s, RegularExpression["(?<=\\d)ef"]]
(* "abcd12cdef" *)
Explanations:
\\d
is a digit character(?<=...)
is a positive look-behind: in this case we only match ef
if it is preceded by \\d
(but we don't include the \\d
in the match)One possible way could be:
lis = {"abcd12efcdef"};
StringReplace[#, k : DigitCharacter ~~ "ef" :> k, 1] & //@ lis
{"abcd12cdef"}
EDIT
lis = {"abcd12efcdef", "abcd12efcdefa12efghef21"};
res1 = StringReplace[#, k : DigitCharacter ~~ "ef" :> k, 1] & //@ lis
res2 = StringReplace[#, k : DigitCharacter .. ~~ "ef" :> k] & /@ lis
{"abcd12cdef", "abcd12cdefa12ghef21"}
res1 == res2
True
res2
is more idiomatic than res1
.
:>
intead of ->
would be better.
$\endgroup$
:>
"better" than ->
when the right-hand side does not need delaying?
$\endgroup$
:>
when it also shows on the rhs. I know in this case it is the pattern name itself. But so not to worry, I just use :>
for all cases. Here is a link post with screen shot from the book which recommends this. so delayed :>
is safer in general.
$\endgroup$
With rules, it is easier, as @Roman and @Syed answers show. However, here is a way to do it without rules:
MyStringReplace[Pattern[lis,
Blank[List]], Pattern[string2,
Blank[]] ? StringQ] := {
StringJoin[
Delete[Flatten @ Map[Characters, lis],
Outer[List,
Flatten[
Map[
Function[
If[
SameQ[DigitQ[Extract[Flatten @ Map[Characters, lis], {#}]],
True],
Range[# + 1, # + 2],
Nothing
]
],
Map[
(# - 1 &) @* ((Apply[Times, #] &) @* First),
Transpose[
Map[
Function @ Position[Flatten @ Map[Characters, lis], #],
Characters @ string2
]
]
]
]
]
]
]
]
};
Examples:
lis0 = {"abcd12efcdef"};
lis1 = {"abcd12efcdefab3ef"};
lis2 = {"abcd12efcdefa12efghef21"};
Tests:
MyStringReplace[lis0, "ef"]
(*{"abcd12cdef"}*)
MyStringReplace[lis1, "ef"]
(*{"abcd12cdefab3"}*)
MyStringReplace[lis2, "ef"]
(*{"abcd12cdefa12ghef21"}*)
s = "abcd12efcdefa12efghef21";
Using SequencePosition
and Threaded
(new in 13.1)
With[{c = Characters @ s},
StringJoin @ Fold[Drop, c, SequencePosition[c, {_?DigitQ, "e", "f"}] +
Threaded[{1, 0}] // Reverse]]
"abcd12cdefa12ghef21"
Also
StringReplace[#, RegularExpression["(\\d)(ef)"] -> "$1"] & /@ lis
(* {"abcd12cdef"} *)
(Keep just the first match)