# Find the position of a string element, knowing only part of the string

I have a list, e.g.:

list = {1, 2, 3, "Element 1", 4, 5, "Element 2", "Something else 1", "etcetera"}


Now, I want all elements starting with "El". Using Position, I could find the position of e.g. "Element 1":

Position[list, "Element 1"]


But, I would like to know the positions of "Element 1" and "Element 2", as both start with "El". So, I would like to have something like

Position[list, "El"_]


I just can't get something like this to work.

Thanks for any help.

• You need string patterns and Friends, e.g. StringFreeQ, StringPosition, .. Commented May 10, 2013 at 19:03
• Commented May 11, 2013 at 7:58

But I would like to know the positions of "Element 1" and "Element 2"...

You can still use Position[]; things are a little more elaborate, though, due to the strings:

Position[list, s_String /; StringMatchQ[s, "El*"]]
{{4}, {7}}

Extract[list, %]
{"Element 1", "Element 2"}

• Great! Thanks a lot - that solved it. Commented May 11, 2013 at 8:02
Select[list, StringMatchQ[ToString@#, "El" ~~ ___] &]


{"Element 1", "Element 2"}

A possibility:

Cases[list, x_String /; StringMatchQ[x, "El*"]]

{"Element 1", "Element 2"}

list = {1, 2, 3, "Element 1", 4, 5, "Element 2", "Something else 1", "etcetera"};


Some more possibilities

Using Pick and the operator form of StringMatchQ

Pick[list, StringMatchQ["El*"] /@ ToString /@ list]


Using SequenceSplit (new in 11.3)

Catenate @ SequenceSplit[list, {_?NumberQ} | {x_ /; StringFreeQ[x, "El"]}]


Using Replace

Replace[list, _?NumberQ | (x_ /; StringFreeQ[x, "El"]) :> Nothing, {1}]


Using GroupBy amd Select

Select[StringStartsQ @ "El"] @ GroupBy[list, Head][String]


All produce

{"Element 1", "Element 2"}

But, I would like to know the positions of "Element 1" and "Element 2", as both start with "El"

Some possibilities using StringStartsQ could be:

list = {1, 2, 3, "Element 1", 4, 5, "Element 2", "Something else 1",
"etcetera"};

Extract[list, Position[list, _String?(StringStartsQ[#, "El"] &)]]

Cases[list, _String?(StringStartsQ[#, "El"] &)]

Select[list, StringQ] // Select[StringStartsQ["El"]]

Select[list, StringQ[#] && StringStartsQ[#, "El"] &]

SequenceCases[list, {x_String /; StringStartsQ[x, "El"]} :> x]


This being mixed Head list, a pre-selection of String heads is required to silence the warnings and errors.

Result:

{"Element 1", "Element 2"}

Using DeleteCases and Except:

DeleteCases[list, Except[x_String /; StringStartsQ[x, "El"]]]

(*{"Element 1", "Element 2"}*)