12

Edit: there is already a question similar to this one but it's for numbers separated by a specific character (Get no. Of words in swift for average calculator). Instead this question is about to get the number of real words in a text, separated in various ways: a line break, some line breaks, a space, more than a space etc.

I would like to get the number of words in a string with Swift 3.

I'm using this code but I get imprecise result because the number is get counting the spaces and new lines instead of the effective number of words.

let str = "Architects and city planners,are  \ndesigning buildings to create  a better quality of life in our urban    areas."
// 18 words, 21 spaces, 2 lines

let components = str.components(separatedBy: .whitespacesAndNewlines)

let a = components.count

print(a)
// 23 instead of 18
Community
  • 1
  • 1
Cue
  • 2,952
  • 3
  • 33
  • 54
  • @LeoDabus I hadn't seen the question you linked or your answer prior to answering this question, but your answer does appear to be both a perfect fit and a correct answer to *this* question. That said, while the answers are more or less identical, both the title and question text are so dissimilar I think it would be hard to find the question you linked given search terms from this question. As such I think it's a stretch to call the question a duplicate. – par Mar 16 '17 at 01:50
  • @LeoDabus I explained how this question is different – Cue Mar 16 '17 at 15:59

1 Answers1

33

Consecutive spaces and newlines aren't coalesced into one generic whitespace region, so you're simply getting a bunch of empty "words" between successive whitespace characters. Get rid of this by filtering out empty strings:

let components = str.components(separatedBy: .whitespacesAndNewlines)
let words = components.filter { !$0.isEmpty }

print(words.count)  // 17

The above will print 17 because you haven't included , as a separation character, so the string "planners,are" is treated as one word.

You can break that string up as well by adding punctuation characters to the set of separators like so:

let chararacterSet = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
let components = str.components(separatedBy: chararacterSet)
let words = components.filter { !$0.isEmpty }

print(words.count)  // 18

Now you'll see a count of 18 like you expect.

par
  • 17,361
  • 4
  • 65
  • 80