# How do I get Replace to work with a complex repeating pattern?

I'm new to Mathematica, but with extensive searching and a lot of experimenting I can't seem to get this to work.

I have a list of strings of the form:

list = { "*A", "B", "*C", "D" , "E", "F", "*G", "H", "*I"};


The elements starting with * can be followed by zero or more elements that don't start with *. I am trying to use pattern matching to construct a function that would for example take f["*C"] and return { "D", "E", "F" }.

I've been trying:

Replace[list, { ___, "*C",
r : Repeated[ y_ /; ! hasStarQ[y]], ___} -> { "*C", r} ]


Where hasStarQ checks if the string starts with *. This almost produces the right result:

{"*C", "D"}


But I can't get it to match "D", "E", "F". Similar results for:

SequenceCases[list, {"*C", Longest[Repeated[ y_ /; ! hasStarQ[y]]]} ]


and

SequenceReplace[list, {___, "*C",
r : Longest[Repeated[ y_ /; ! hasStarQ[y]]], Shortest@___} :> r]


I recognise that I can achieve what I need using SplitBy but I wonder whether there is a more elegant way to achieve this goal!

• SequenceCases[list, {"*C", x__?(NoneTrue[{##}, StringStartsQ["*"]] &)} :> {x}]?
– kglr
Commented Jan 27 at 6:15

SequenceCases[list,
{"*C", x__} /;  Nor @@ StringStartsQ[{x}, "*"] :> {x}]

{{"D", "E", "F"}}

Cases[{"*C", x___} :> {x}]@Split[list, Not@StringStartsQ["*"]@#2 &]

{{"D", "E", "F"}}

• Many thanks. So the trick is to test the whole results list rather than the individual elements. Commented Jan 27 at 8:46
list = {"*A", "B", "*C", "D", "E", "F", "*G", "H", "*I"};


Build and query an Association

look =
GroupBy[#, First -> Rest, First]& @ Split[list, !StringStartsQ[#2, "*"] &]


<|"*A" -> {"B"}, "*C" -> {"D", "E", "F"}, "*G" -> {"H"}, "*I" -> {}|>

look["*C"]


{"D", "E", "F"}

Lookup[look, {"*A", "*C", "*X"}, {}]


{{"B"}, {"D", "E", "F"}, {}}

list = {"*A", "B", "*C", "D", "E", "F", "*G", "H", "*I"};


Using SequenceSplit:

rep = {__, "*C", x__} /; Nor @@ StringStartsQ[{x}, "*"] :> {x};

Select[SequenceSplit[list, rep], ContainsOnly[StringFreeQ[#, "*"], {True}] &]

(*{{"D", "E", "F"}}*)


Or using SequenceReplace:

Cases[{__}]@SequenceReplace[list, rep]

(*{{"D", "E", "F"}}*)