Dear Erica: String matching without Foundation

Dear Erica, what is the best way to string.contains(substring) … without Foundation?

Of course, after this initial query, I was told what he wanted was really hasPrefix and not contains. This led me on a merry chase through strstr and a bunch of other ridiculous approaches, until Mike Ash suggested using startsWith and SequenceType.

The following contains ended up being pretty brute force (there’s a better version by Oisin K below) but prefixedBy does what seems to be needed. I renamed it so it didn’t overlap with the existing OS X hasPrefix.

And here’s the much nicer version from Oisin Kidney, which performs a kind of mapcdr approach.

Oisin points out that you also may want to check out this Swift version of the Boyer-Moore algorithm by Marcin Krzyżanowski.

So I probably could have spent a half an afternoon more productively but it was nice to dive back into C interop, especially touching base with pointers (strstr returns a pointer offset, so no Swift value types thank you) and remembering how to allocate, write to, and use memory directly. So not a complete waste.

It should be noted that my limited interest in diacriticals and other niceties would have come into play eventually. Using Swift-specific solutions offer a much better approach.

6 Comments

  • I am missing something, or should

    if caseSensitive { return lowercaseString.contains(s.lowercaseString) }

    read

    if !caseSensitive { return lowercaseString.contains(s.lowercaseString) }

    ?

    Regardless, I’d like to note that I’m extremely grateful for your enduring effort. It has been a real boon and inspiration to me.

    • I forwarded your message to Oisin

      • Thanks, and sorry for the bother.

        • Thanks right back at you. And Oisin sends his thanks as well. If you reload the page, you’ll see your fix is in-place.

  • For comparisons where the sophisticated handling of Unicode available in Swift is not necessary, using strstr seems to be the easiest solution.

    func contains(substring: String, caseSensitive: Bool = true) -> Bool {
    if caseSensitive {
    return strstr(self, substring) != nil
    } else {
    return strcasestr(self, substring) != nil
    }
    }

  • Hmmm. The GitHub code snippets don’t make it to the RSS feed. Not sure if that’s fixable, but it would be nice.