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

6 Answers 6

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
    Sep 6, 2019 at 4:53
  • $\begingroup$ :> m in Cases is not necessary. $\endgroup$ Sep 6, 2019 at 7:48
  • $\begingroup$ @ΑλέξανδροςΖεγγ Thanks. $\endgroup$
    – C. E.
    Sep 6, 2019 at 9:31
6
$\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$
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
    Sep 2, 2023 at 17:47
  • $\begingroup$ Try with: ReplaceAt[lis, _ -> (If[StringStartsQ[#[[1]], "a"], #, Nothing] &)@* List, {All, 0}] $\endgroup$ Sep 2, 2023 at 20:42
2
$\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
    Sep 2, 2023 at 17:40
  • $\begingroup$ Thanks, mate! :-) $\endgroup$ Sep 2, 2023 at 17:43

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.