0

Say if I have a sentence:

a fox jumps over another fox

I need to map it to a list of words with their corresponding range inside the string, for example, the first "fox" should map to:

["fox", NSRange(2, 3)]

the difficulty here is duplicated words like the two "fox", I can check the index of each word in the string, and remove the word (from the string) as I go, but is there a smarter way of doing this?

Another challenge is when a word has dot in it, say:

a fox jumps over another f.x

if I search the range for "f.x" probably it would also match "fox"?

Thanks!

2
  • So you only want the first occurrence of a word if a word is duplicated? Commented Dec 15, 2020 at 2:14
  • Thanks @Sweeper I want each word in the sentence and their range in the sentence, for example the two "fox" in "fox jumps over another fox" should give me ("fox", range1) and ("fox", range2) where range1 and range2 are different. Commented Dec 15, 2020 at 2:25

1 Answer 1

3

You can use String method enumerateSubstrings(in:, options:) and use byWords options:

func enumerateSubstrings<R>(in range: R, options opts: EnumerationOptions = [], _ body: @escaping (String?, Range<Index>, Range<Index>, inout Bool) -> Void) where R : RangeExpression, R.Bound == Index

extension String {
    var byWordsAndRanges: [(String, Range<Index>)] {
        var wordsAndRanges: [(String, Range<Index>)] = []
        enumerateSubstrings(in: startIndex..., options: .byWords) { word, range, _, _ in
            // The force unwrap of word is safe. It will only be nil if `substringNotRequired` is included in opts
            wordsAndRanges.append((word!, range))
        }
        return wordsAndRanges
    }
}

let test = "a fox jumps over another fox"
for (word, range) in test.byWordsAndRanges {
    print("word:", word)
    print("substring:", test[range])

}

This will print:

word: a
substring: a
word: fox
substring: fox
word: jumps
substring: jumps
word: over
substring: over
word: another
substring: another
word: fox
substring: fox

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.