Skip to content

Instantly share code, notes, and snippets.

@greister
Forked from erica/MoreSwifty.swift
Created December 31, 2015 15:10
Show Gist options
  • Save greister/5b2d4b235bf215c86038 to your computer and use it in GitHub Desktop.
Save greister/5b2d4b235bf215c86038 to your computer and use it in GitHub Desktop.
extension String {
/// Range of first match to string
func rangeOfString(searchString: String) -> Range<Index>? {
// If equality, return full range
if searchString == self {return startIndex..<endIndex}
// Basic sanity checks
let (count, stringCount) = (characters.count, searchString.characters.count)
guard !isEmpty && !searchString.isEmpty && stringCount < count
else {return nil}
// Moving search offset. Thanks Josh W
let stringCharacters = characters
let searchCharacters = searchString.characters
var searchOffset = stringCharacters.startIndex
let searchLimit = stringCharacters.endIndex.advancedBy(-stringCount)
var failedMatch = true
// March character checks through string
while searchOffset <= searchLimit {
failedMatch = false
// Enumerate through characters
for (idx, c) in searchCharacters.enumerate() {
if c != stringCharacters[searchOffset.advancedBy(idx)] {
failedMatch = true; break
}
}
// Test for success
guard failedMatch else {break}
// Offset search by one character
searchOffset = searchOffset.successor()
}
return failedMatch ? nil : searchOffset..<searchOffset.advancedBy(stringCount)
}
/// Mimic NSString's version
func componentsSeparatedByString(separator: String) -> [String] {
var components: [String] = []
var searchString = self
// Find a match
while let range = searchString.rangeOfString(separator) {
// Break off first item (thanks Josh W)
let searchStringCharacters = searchString.characters
let first = String(searchStringCharacters.prefixUpTo(range.startIndex))
if !first.isEmpty {components.append(first)}
// Anything left to find?
if range.endIndex == searchString.endIndex {
return components.isEmpty ? [self] : components
}
// Move past the separator and continue
searchString = String(searchStringCharacters.suffixFrom(range.endIndex))
}
if !searchString.isEmpty {
components.append(searchString)
}
return components
}
}
let tests: [(String, String, [String])] = [
("", "", [""]),
(" ", "", [" "]),
("plugh ", " ", ["plugh"]),
(" plugh", " ", ["plugh"]),
(" plugh ", " ", ["plugh"]),
("the time has come the ", " ", ["the", "time", "has", "come", "the"]),
(" the time has come the ", " ", ["the", "time", "has", "come", "the"]),
("the time has come the", " ", ["the", "time", "has", "come", "the"]),
("*&&*the*&&*time*&&*has*&&*", "*&&*", ["the", "time", "has"]),
("a", "abc", ["a"])
]
for test in tests
{
let results = test.0.componentsSeparatedByString(test.1)
debugPrint(results == test.2 ? "Pass" : "Fail", test.0, test.1, separator:", ")
// debugPrint(test.0, test.1, test.0.rangeOfString(test.1))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment