7
$\begingroup$

I have a list of strings:

lis = {"a","b","c","12","d","q","r","X","s"}

I'd like to delete list members starting with "X" moving backwards through the list from "X" until a list member that's a digit character is found, to get:

res = {"a","b","c","12","s"}

Not sure how to use DeleteCases here?

$\endgroup$

6 Answers 6

7
$\begingroup$

You would need something like DeleteSubsequenceCases, but it doesn't exist. I would recommend this instead:

SequenceReplace[lis, {d_?(StringMatchQ[NumberString]), ___, "X"} :> d]

If X only appears once, you could also use this:

First@SequenceCases[lis, {a___, d_?(StringMatchQ[NumberString]), ___, "X", b___} :> {a, "12", b}]
$\endgroup$
5
$\begingroup$
Replace[lis, {a___, b_String?(StringMatchQ[NumberString]), Shortest[c___], "X", d___} :> 
  {a, b, d}]

{"a", "b", "c", "12", "s"}

$\endgroup$
4
$\begingroup$
rlis = Reverse[lis];
xpos = First[Flatten[Position[StringMatchQ[rlis, "X"], True]]];
Reverse[Drop[rlis, {xpos, xpos + LengthWhile[rlis[[xpos + 1 ;;]], 
     StringMatchQ[#, NumberString] == False &]}]]

{"a", "b", "c", "12", "s"}

$\endgroup$
4
$\begingroup$

This was a good opportunity to use Cases and compare it with other presented techniques.

I have added another entry in lis2 that is a NumberString in order to experiment.

lis2 = {"a", "b", "c", "12", "d", "13", "q", "r", "X", "s"}

Cases[Reverse@lis2
   , {
     g___
     , "X"
     , Longest[_String?(FreeQ[NumberString]) ..], 
     s_?(StringMatchQ[NumberString])
     , h___
     } :> {g, s, h}, All] // First // Reverse

{"a", "b", "c", "12", "s"}

The extra layer of {} is removed with First. This can be avoided by modifying the last line above as follows:

... } :> Sequence @@ {g, s, h}, All] // Reverse

It also helps to have the the list displayed in reverse order as one is writing the pattern.

Without the Longest pattern object:

Cases[Reverse@lis2
   , {
     g___
     , "X"
     , _String?(FreeQ[NumberString]) ..
     , s_?(StringMatchQ[NumberString])
     , h___} :> {g, s, h}, All] // First // Reverse

{"a", "b", "c", "12", "d", "13", "s"}

$\endgroup$
2
$\begingroup$

Using Partition and ReplaceAll:

ReplaceAll[
    Last[
        Map[Function[Join @@ If[SameQ[FreeQ[#, "X"], True], #, Nothing]],
            Map[Function @ Partition[lis, {#}], Range @ Length @lis]
        ]
    ],
    {x__, "12", y__} :> {x, 12, "s"}
 ]

(*{"a", "b", "c", 12, "s"}*)
$\endgroup$
1
$\begingroup$
list = {"a", "b", "c", "12", "d", "q", "r", "X", "s"};

With[{
  a = {Last @ Position[list, _String?(StringMatchQ[#, NumberString] &)]},
  b = Position["X"] @ list},
 MapAt[Nothing, list, Span @@ (Flatten[{a, b}] + {1, 0})]]

{"a", "b", "c", "12", "s"}

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