12
$\begingroup$

I am trying to find a string within a string, but "anywhere", so long as it is in the right order.

For example

StringContainsQ["aabbc","ac"]

returns

False

but I want True, since ac does in fact occur interleaved as position 1 and then position 5 in aabbc, as well as at position 2 and then position 5.

Anywhere, but in the right order. So

For example

NewStringContainsQFunction["aabbc","ba"]

should return.

False

Is there a nice way to do this, apart from searching letter by letter, until the string is built?

$\endgroup$

5 Answers 5

18
$\begingroup$
StringMatchQ["aabbc", "*a*c*"]

True

StringMatchQ["aabbc", "*b*a*"]

False

You can also use LongestCommonSequence to construct a function

ClearAll[strngCntnsQ]
strngCntnsQ = LongestCommonSequence[##] == #2 &;

strngCntnsQ["aabbc", "ac"]

True

strngCntnsQ["aabbc", "ba"]

False

$\endgroup$
3
  • 1
    $\begingroup$ The second function is by far the best answer on here, since it immediately generalizes to longer second strings without needing to tweak it with *s etc. $\endgroup$ Commented Jan 29, 2020 at 1:27
  • 2
    $\begingroup$ @GregMartin That's true, but it's also far slower than a simple string pattern for non-trivial amounts of data. If you need efficiency, regular expressions or string patterns are much better. $\endgroup$ Commented Jan 29, 2020 at 9:14
  • 5
    $\begingroup$ @GregMartin StringRiffle[Characters@"whatever", {"*", "*", ""}] $\endgroup$
    – Kuba
    Commented Jan 29, 2020 at 9:30
15
$\begingroup$

Is this what you need?

StringContainsQ["aabbc","a" ~~ ___ ~~ "c"]

True

The following documentation pages should help you get going with string patterns in Wolfram Language:

https://reference.wolfram.com/language/tutorial/StringPatterns.html https://reference.wolfram.com/language/tutorial/WorkingWithStringPatternsOverview.html

edit Here is a function that generalizes this idea to strings of arbitrary length:

NewStringContainsQFunction[str1_String, str2_String] := 
  StringContainsQ[
    str1,
    StringExpression @@ Riffle[Characters[str2], ___]
  ]

NewStringContainsQFunction["aabbc", "ac"]
NewStringContainsQFunction["aabbc", "ba"]
NewStringContainsQFunction["aadbebfc", "abc"]

True

False

True

$\endgroup$
7
$\begingroup$
StringContainsQ["aaabc", RegularExpression["a.*c"]]

True

$\endgroup$
3
$\begingroup$

A variant of NewStringContainsQFunction using StringPosition:

NewStringContainsQFunction[str1_String, str2_String] := 
AllTrue[Differences@(Last @@@ (Splice@StringPosition[str1, #] & /@ 
Characters@str2)), Positive]

NewStringContainsQFunction["aabbc", "ac"]
NewStringContainsQFunction["aabbc", "ba"]
NewStringContainsQFunction["aadbebfc", "abc"]

True
False
True

$\endgroup$
2
$\begingroup$
c = Characters["aabbckkdf"];

s = Characters["acd"];

Using DeleteElements (new in 13.1)

DeleteElements[DeleteDuplicates @ c, Complement[c, s]] == s

True

$\endgroup$
1
  • $\begingroup$ (–1). This doesn't work if there are multiple occurences of the same character in the search string, for example c = Characters["aba"]; s = Characters["aa"];. $\endgroup$
    – Domen
    Commented Jun 18 at 9:12

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.