Number of words in a Swift String for word count calculation
update: Xcode 10.2.x • Swift 5 or later
Using Foundation method enumerateSubstrings(in: Range)
and setting .byWords
as options:
let sentence = "I want to an algorithm that could help find out how many words are there in a string separated by space or comma or some character. And then append each word separated by a character to an array which could be added up later I'm making an average calculator so I want the total count of data and then add up all the words. By words I mean the numbers separated by a character, preferably space Thanks in advance"
var words: [Substring] = []
sentence.enumerateSubstrings(in: sentence.startIndex..., options: .byWords) { _, range, _, _ in
words.append(sentence[range])
}
print(words) // "["I", "want", "to", "an", "algorithm", "that", "could", "help", "find", "out", "how", "many", "words", "are", "there", "in", "a", "string", "separated", "by", "space", "or", "comma", "or", "some", "character", "And", "then", "append", "each", "word", "separated", "by", "a", "character", "to", "an", "array", "which", "could", "be", "added", "up", "later", "I\\'m", "making", "an", "average", "calculator", "so", "I", "want", "the", "total", "count", "of", "data", "and", "then", "add", "up", "all", "the", "words", "By", "words", "I", "mean", "the", "numbers", "separated", "by", "a", "character", "preferably", "space", "Thanks", "in", "advance"]\n"
print(words.count) // 79
Or using native Swift 5 new Character
property isLetter
and the split method:
let words = sentence.split { !$0.isLetter }
print(words) // "["I", "want", "to", "an", "algorithm", "that", "could", "help", "find", "out", "how", "many", "words", "are", "there", "in", "a", "string", "separated", "by", "space", "or", "comma", "or", "some", "character", "And", "then", "append", "each", "word", "separated", "by", "a", "character", "to", "an", "array", "which", "could", "be", "added", "up", "later", "I", "m", "making", "an", "average", "calculator", "so", "I", "want", "the", "total", "count", "of", "data", "and", "then", "add", "up", "all", "the", "words", "By", "words", "I", "mean", "the", "numbers", "separated", "by", "a", "character", "preferably", "space", "Thanks", "in", "advance"]\n"
print(words.count) // 80
Extending StringProtocol
to support Substrings as well:
extension StringProtocol {
var words: [SubSequence] {
return split { !$0.isLetter }
}
var byWords: [SubSequence] {
var byWords: [SubSequence] = []
enumerateSubstrings(in: startIndex..., options: .byWords) { _, range, _, _ in
byWords.append(self[range])
}
return byWords
}
}
sentence.words // ["I", "want", "to", "an", "algorithm", "that", "could", "help", "find", "out", "how", "many", "words", "are", "there", "in", "a", "string", "separated", "by", "space", "or", "comma", "or", "some", "character", "And", "then", "append", "each", "word", "separated", "by", "a", "character", "to", "an", "array", "which", "could", "be", "added", "up", "later", "I", "m", "making", "an", "average", "calculator", "so", "I", "want", "the", "total", "count", "of", "data", "and", "then", "add", "up", "all", "the", "words", "By", "words", "I", "mean", "the", "numbers", "separated", "by", "a", "character", "preferably", "space", "Thanks", "in", "advance"]
How to get the number of real words in a text in Swift
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.
Word Count in Swift
Your method was pretty solid, but this makes a couple improvements. I store the value count using Swifts "if let" keyword to check for an optional value. Then I can use count when updating the dictionary. I used the shorthand notation for updateValue (dict[key] = val). I also split the original string on all whitespace instead of just a single space.
func wordCount(s: String) -> Dictionary<String, Int> {
var words = s.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
var wordDictionary = Dictionary<String, Int>()
for word in words {
if let count = wordDictionary[word] {
wordDictionary[word] = count + 1
} else {
wordDictionary[word] = 1
}
}
return wordDictionary
}
Swift 4 iOS - Word Count from UITextField
That's because your textview has no text in it at that point.
Try this:
INPUT.text = "Some Text"
Do get the text from an actual input:
INPUT.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
func textFieldDidChange(_ textField: UITextField) {
let strings : String! = INPUT.text
let spaces = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
let words = strings.components(separatedBy: spaces)
print(words.count)
}
Calculating word count from a url in swift
First of all, you need to parse the HTML. HTML can only be parsed reliably with dedicated HTML parser. Please don't use Regular Expressions or any other search method to parse HTML. You may read it why from this link. If you are using swift, you may try Fuzi or Kanna. After you get the body text with any one of the library, you have to remove extra white spaces and count the words. I have written some basic code with Fuzi library for you to get started.
import Fuzi
// Trim
func trim(src:String) -> String {
return src.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
// Remove Extra double spaces and new lines
func clean(src:String) ->String {
return src.replacingOccurrences(
of: "\\s+",
with: " ",
options: .regularExpression)
}
let htmlUrl = URL(fileURLWithPath: ((#file as NSString).deletingLastPathComponent as NSString).appendingPathComponent("test.html"))
do {
let data = try Data(contentsOf: htmlUrl)
let document = try HTMLDocument(data: data)
// get body of text
if let body = document.xpath("//body").first?.stringValue {
let cleanBody = clean(src: body)
let trimmedBody = trim(src:cleanBody)
print(trimmedBody.components(separatedBy: " ").count)
}
} catch {
print(error)
}
If you are fancy, you may change my global functions to String
extension or you can combine them in a single function. I wrote it for clarity.
How can I count the number of sentences in a given text in Swift?
Just add the character in charset
by which you are going to differentiate your sentences:
I am assuming ? . ,
for now:
let input = "That would be the text. it hast 3? periods."
let charset = CharacterSet(charactersIn: ".?,")
let arr = input.components(separatedBy: charset)
let count = arr.count - 1
Here arr
would be:
["That would be the text", " it hast 3", " periods", ""]
decrease count by 1, to get actual sentences.
Note: If you don't want to consider " , "
then remove it from charset
.
Related Topics
Inter-App Data Migration (Migrating Data to New App Version)
How to Update the Constant Height Constraint of a Uiview Programmatically
Rounding a Double Value to X Number of Decimal Places in Swift
Segue and Button Programmatically Swift
Append Text or Data to Text File in Swift
Swift 3 Incorrect String Interpolation With Implicitly Unwrapped Optionals
Any Way to Replace Characters on Swift String
How to Deal With @Objc Inference Deprecation With #Selector() in Swift 4
Examples of Delegates in Swift
How to Use String.Substringwithrange? (Or, How Do Ranges Work in Swift)
Error-Handling in Swift-Language
Nsdate() or Date() Shows the Wrong Time
How to Check If a String Contains Another String in Swift
Read and Write a String from Text File