10
$\begingroup$

I have a list each element of which consists of a list containing two strings and two integers:

lis = {{"ab", 2, "c", 3}, {"d", 3, "e", 4}, {"ac", 5, "f", 6}, {"c", 7, "d", 8}, {"ad", 9, "c", 10}}

I would like to create a new list that includes every member of lis whose first element starts with "a":

res = {{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

This would seem to be a simple task for StringCases, but I am not having much luck; suggestions would be gratefully received.

$\endgroup$
0

8 Answers 8

4
$\begingroup$
Pick[lis, StringTake[lis[[All, 1]], 1], "a"]

Pick[lis, StringPart[lis[[All, 1]], 1], "a"]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Less elegantly readable ones that use ToCharacterCode:

Pick[lis, 
 First@ToCharacterCode@First@# == Sequence @@ ToCharacterCode["a"] & /@
   lis]

Pick[lis, 
 lis[[All, 1]] /. s_String -> ToCharacterCode[s] // Map[First], 
 Sequence @@ ToCharacterCode["a"]]
$\endgroup$
12
$\begingroup$

Some options:

Pick[
 lis,
 StringStartsQ[lis[[All, 1]], "a"]
 ]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Select[lis, StringStartsQ[First[#], "a"] &]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Cases[lis, {_?(StringStartsQ["a"]), ___}]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

$\endgroup$
3
  • $\begingroup$ Thank you for the options, I'll check which is faster with a large data set I have. $\endgroup$
    – Suite401
    Commented Sep 6, 2019 at 4:53
  • $\begingroup$ :> m in Cases is not necessary. $\endgroup$ Commented Sep 6, 2019 at 7:48
  • $\begingroup$ @ΑλέξανδροςΖεγγ Thanks. $\endgroup$
    – C. E.
    Commented Sep 6, 2019 at 9:31
7
$\begingroup$

Alternate solutions using string patterns:

Pick[lis, StringMatchQ[lis[[All, 1]], "a" ~~ ___]]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Pick[lis, StringCases[lis[[All, 1]], "a" ~~ ___] // Map[Length], 1]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Pick[lis, StringPosition[lis[[All, 1]], "a" ~~ ___] // Map[MatrixQ]]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

$\endgroup$
5
$\begingroup$

A few additional variations:

Pick[lis, StringMatchQ["a*"]@lis[[All, 1]]]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Pick[lis, StringTake[lis[[All, 1]], 1], "a"]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Pick[lis, Order[#, "b"]& /@ lis[[All, 1]], 1]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

$\endgroup$
4
$\begingroup$

Another way using ReplaceAll:

lis /. x : {___} /; StringQ[x[[1]]] :> If[StringStartsQ[x[[1]], "a"], x, Nothing]

(*{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}*)
$\endgroup$
2
  • 1
    $\begingroup$ Why is it different from res in the OP? $\endgroup$
    – Syed
    Commented Sep 2, 2023 at 17:40
  • $\begingroup$ Thanks, mate! :-) $\endgroup$ Commented Sep 2, 2023 at 17:43
2
$\begingroup$
ReplaceAt[lis, _?(Not @* StringStartsQ["a"]) :> Nothing, {All, 1}]

{{"ab", 2, "c", 3}, {3, "e", 4}, {"ac", 5, "f", 6}, {7, "d", 8}, {"ad", 9, "c", 10}}

$\endgroup$
2
  • 1
    $\begingroup$ This is different from res in the OP? $\endgroup$
    – Syed
    Commented Sep 2, 2023 at 17:47
  • $\begingroup$ Try with: ReplaceAt[lis, _ -> (If[StringStartsQ[#[[1]], "a"], #, Nothing] &)@* List, {All, 0}] $\endgroup$ Commented Sep 2, 2023 at 20:42
2
$\begingroup$
list = 
  {{"ab", 2, "c", 3}, {"d", 3, "e", 4}, {"ac", 5, "f", 6}, 
   {"c", 7, "d", 8}, {"ad", 9, "c", 10}};

Using Extract

p = Position[list, {a_String /; StringStartsQ[a, "a"], __}]

Extract[p] @ list

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

Using SequenceSplit (new in 11.3)

Catenate @ SequenceSplit[list, {{x_ /; Not @ StringStartsQ[x, "a"], __}}]

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

$\endgroup$
1
$\begingroup$

Using Association and Merge

lis = {{"ab", 2, "c", 3}, {"d", 3, "e", 4}, {"ac", 5, "f", 6}, {"c", 7,
     "d", 8}, {"ad", 9, "c", 10}};
"a" /. Merge[Association[StringTake[#[[1]], 1] -> #] & /@ lis, 
  Identity]

gives:

{{"ab", 2, "c", 3}, {"ac", 5, "f", 6}, {"ad", 9, "c", 10}}

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