3
$\begingroup$

I have a string like this one

str = "this and that but also thit and that";

Now I want to extract, the first 3 letters before and after " and " so that the outcome is

{his and tha, hit and tha}

I tried it with

StringCases[str, 
 x__ ~~ " and " ~~ y__ :> {StringTake[x, -3], StringTake[y, 3]}]

but this extracts only the second substring {{"hit", "tha"}}. And using StringCases[str, _ ~~ " and " ~~ _] extracts only one letter {"s and t", "t and t"}. So is there a way to define a Blank with a particular length?

$\endgroup$
2

3 Answers 3

4
$\begingroup$
StringCases[str,   x__ ~~ " and " ~~ y__ /; StringLength[x] == StringLength[y] == 3]

or

StringCases[str, _ ~~ _ ~~ _ ~~ " and " ~~ _ ~~ _ ~~ _]

would work:

{"his and tha", "hit and tha"}
$\endgroup$
6
$\begingroup$

Using Repeated:

StringCases[
 str,
 Repeated[_, {3}] ~~ " and " ~~ Repeated[_, {3}],
 Overlaps -> True
 ]

{"his and tha", "hit and tha"}

Note the use of Overlaps which is necessary for strings such as

str = "this and that and thit and that";

With Overlaps -> True:

{"his and tha", "hat and thi", "hit and tha"}

with Overlaps -> False:

{"his and tha", "hit and tha"}

$\endgroup$
1
  • $\begingroup$ Your solution is neater and more detailed! $\endgroup$ Jul 2, 2020 at 3:56
2
$\begingroup$

If the number of whitespaces before and after 'and' is unknown (but in each case there is at least one), a simple regex should do:

str = "this and that but also thit and that";
StringCases[str, RegularExpression[".{3}\s+and\s+.{3}"]]

{his and tha, hit and tha}

Alternatively, a positive lookahead may be used:

StringCases[str, RegularExpression["(?=(.{3}\s+and\s+.{3}))\\1"]]
StringCases[str, RegularExpression["(?=(.{3}\s+and\s+.{3}))"]:> "$1"]

{his and tha, hit and tha}

{his and tha, hit and tha}


For strings such as "this and that and thit and that" considered by C.E above:

str2 = "this and that and thit and that";
StringCases[str2, RegularExpression[".{3}\s+and\s+.{3}"], Overlaps:> True]
StringCases[str2, RegularExpression["(?=(.{3}\s+and\s+.{3}))\\1"],Overlaps->True]
StringCases[str2, RegularExpression["(?=(.{3}\s+and\s+.{3}))"]:> "$1"]

{his and tha, hat and thi, hit and tha}

{his and tha, hat and thi, hit and tha}

{his and tha, hat and thi, hit and tha}

In addition posix character classes are supported:

StringCases[str2, RegularExpression["[[:alnum:]]{3}[[:blank:]][Aa]nd[[:blank:]][[:alnum:]]{3}"], Overlaps:> True]

{his and tha, hat and thi, hit and tha}


For positive lookaheads, compare (see here):

s = "123456789123456789";
StringCases[s,RegularExpression["(?=(\d{10}))\\1"]]
StringCases[s,RegularExpression["(?=(\d{10}))\\1"],Overlaps:>True]
StringCases[s,RegularExpression["(?=(\d{10}))"]:> "$1"]

{1234567891}

{1234567891, 2345678912, 3456789123, 4567891234, 5678912345, 6789123456, 7891234567, 8912345678, 9123456789}

{1234567891, 2345678912, 3456789123, 4567891234, 5678912345, 6789123456, 7891234567, 8912345678, 9123456789}

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.