0

I have a list of words that I am trying to match into an input string in Swift. For example, each time one of these words appears in the string, I would like to print it and add one to a variable. I have gotten as far as being able to determine if the word appears in the sentence once, but not if it is in the string more than once. Here is my code...

import Swift
import Foundation

var dictionary: [String] = 
["blue",
"red",
"yellow",
"green"]

var count = dictionary.count

var string = "blue yellow red green blue red"

var value = 0

for var index = 0; index < count; index++ {
    if string.lowercaseString.rangeOfString(dictionary[index]) != nil {
            print("\(dictionary[index])")
            value++
            print("\(dictionary[index]) is a flagged word")
            print(value)
    }
}

Doing this would only put the value at 4 (should be 6), because it would only count each word once and would ignore the other blue and red substrings. Is there a workaround for this? I could not find any info on this, thanks.

  • This might help you: http://stackoverflow.com/questions/31746223/swift-number-of-occurrences-of-substring-in-string – egor.zhdan Feb 22 '16 at 21:29
  • perfect, it worked well...don't know how I missed that one – user3354279 Feb 22 '16 at 21:48
  • 1
    You should try to avoid the `for;;` loop, it's going to be removed in a future version of Swift and is very un-Swifty. Instead use something like `for word in dictionary {...}` –  Feb 22 '16 at 22:56
  • @KennethBruno even `for word in dictionary` should usually be replaced with some form or combination of `map`, `flatMap`, `filter` and/or `reduce` – David Berry Feb 22 '16 at 23:04
  • @DavidBerry I agree that those functions are great in many situations but it's just as valid to use a `for...in` loop for sake of clarity. It comes down to programming style. –  Feb 22 '16 at 23:06

1 Answers1

2

Easiest way is to combine componentsSeparatedByString and reduce:

var count = string.componentsSeparatedByString(" ").reduce(0) {
   words.contains($1) ? $0 + 1 : $0 
}

Although this doesn't do exactly the same thing as your example because it assumes your actually looking for words in your dictionary. If you're actually just looking for string matches, try:

var count2 = words.map({
    string.componentsSeparatedByString($0).count - 1
}).reduce(0, combine:+)
David Berry
  • 40,941
  • 12
  • 84
  • 95
  • The second example is a clever way to perform this task. However it's probably inscrutable to people not familiar with this technique and should be accompanied with some explanation. –  Feb 22 '16 at 23:04
  • Probably, over the next few years of swift development I think (hope) that everybody will become familiar enough with the functional/declarative mechanisms of swift (map, flatMap, filter, reduce) that verbose explanations of such structures will become unnecessary :) – David Berry Feb 22 '16 at 23:06
  • I agree, they are very powerful and useful. Used properly and judiciously they can do much to simplify and clarify code. Until then we just have to teach it to all! –  Feb 22 '16 at 23:07
  • Yeah, once you understand what they mean, and how universally they apply, it almost becomes a "well duh" moment. – David Berry Feb 22 '16 at 23:08