Skip to content

Instantly share code, notes, and snippets.

@mathonsunday
Last active March 10, 2019 01:07
Show Gist options
  • Select an option

  • Save mathonsunday/ef56941c644e3161c473a50af81508d6 to your computer and use it in GitHub Desktop.

Select an option

Save mathonsunday/ef56941c644e3161c473a50af81508d6 to your computer and use it in GitHub Desktop.
import Foundation
import PlaygroundSupport
func wordsWith(prefix: String, in dictionary: [String]) -> [String] {
var output: [String] = []
let prefixCount = prefix.count
let prefixCharArray = Array(prefix)
wordLoop: for word in dictionary {
let charArray = Array(word)
var wordIndex = 0
var prefixIndex = 0
while prefixIndex < prefixCount {
if charArray[wordIndex] != prefixCharArray[prefixIndex] {
continue wordLoop
}
wordIndex += 1
prefixIndex += 1
}
output.append(word)
}
return output
}
let dictionary = ["CAT", "DOG", "BUNNY", "CAN", "CUT", "DOLL"]
print(wordsWith(prefix: "CA", in: dictionary))
@joshgebara
Copy link
Copy Markdown

joshgebara commented Mar 10, 2019

If we need to implement hasPrefix ourselves, then I feel like the zip function would work well here as a good way to iterate through the two strings character by character without having to manually deal with tracking and updating indices.

It eliminates having to worry about the index out of bounds errors that @eneko brought up and still works in situations where the prefix is longer than the word since the zip function will stop when one of the sequences it is supplied as input has no more remaining elements.

There is also an added benefit that it allows for a more generic extension on Sequence. If we are manually subscripting and tracking the indices as an Int, then the most generic we could get would be an extension on Collection with a where clause specifying that the collection's Index is an Int.

The only problem I see with this custom implementation of hasPrefix is if the function must be case insensitive. Since the only requirement of this extension is that the Element conforms to Equatable we'd have to further constrain Element to get access to the lowercased() method.

extension Sequence where Element: Equatable {
    func hasPrefix<Prefix: Sequence>(_ prefix: Prefix) -> Bool where Element == Prefix.Element {
        for (element, prefixElement) in zip(self, prefix) {
            if element != prefixElement {
                return false
            }
        }
        return true
    }
}

extension Sequence where Element == String {
    func wordsWith(prefix: String) -> [String] {
        return filter { $0.hasPrefix(prefix) }
    }
}

let dictionary = ["CAT", "DOG", "BUNNY", "CAN", "CUT", "DOLL"]
dictionary.wordsWith(prefix: "CA") // CAT, CAN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment