Swift中的单词计数

6

在Swift中,有没有更优雅的方式来编写一个简单的单词计数功能?

//Returns a dictionary of words and frequency they occur in the string
func wordCount(s: String) -> Dictionary<String, Int> {
    var words = s.componentsSeparatedByString(" ")
    var wordDictionary = Dictionary<String, Int>()
    for word in words {
        if wordDictionary[word] == nil {
            wordDictionary[word] = 1
        } else {
            wordDictionary.updateValue(wordDictionary[word]! + 1, forKey: word)
        }
    }
    return wordDictionary
}

wordCount("foo foo foo bar")
// Returns => ["foo": 3, "bar": 1]

5
我打算保留这个问题。通过阅读不同的实现方式,Swift社区可以学习语言特性。 "优雅" 意味着利用语法糖、可读性、简洁甚至是性能。此外,允许引起众多不同答案的主观问题也有很多先例。例如这里 - mmla
4个回答

11

你的方法非常可靠, 但这里有几处改进。我使用Swift中的"if let"关键字来检查可选值并存储值的计数。然后在更新字典时,就可以使用计数值。我还使用了updateValue的简写形式 (dict[key] = val)。同时我将原始字符串根据所有的空格进行分割,而不是只根据一个空格。

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
}

如果计数允许 - mmla
太棒了!很高兴我能帮到你 :) - Dash
1
在 Swift 5 中,您可以使用 var words = s.components(separatedBy: NSCharacterSet.whitespaces) 获取单词列表。 - Roy

3

我认为这并不更加优雅,因为可读性很差,而且需要使用Dictionary的扩展,但是编写它确实非常有趣,并展示了Swift的潜在强大功能:

extension Dictionary {
    func merge(with other: [KeyType:ValueType], by merge: (ValueType, ValueType) -> ValueType) -> [KeyType:ValueType] {
        var returnDict = self
        for (key, value) in other {
            var newValue = returnDict[key] ? merge(returnDict[key]!, value) : value
            returnDict.updateValue(newValue, forKey: key)
        }
        return returnDict
    }
}

func wordCount(s: String) -> [String:Int] {
    return s.componentsSeparatedByString(" ").map {
        [$0: 1]
    }.reduce([:]) {
        $0.merge(with: $1, +)
    }
}
wordCount("foo foo foo bar")

我认为合并扩展在其他情况下也会很有用


我从这个例子中学到了大约三个关于Swift的知识点。谢谢! - mmla
@MichaelM 太棒了!我很高兴它有帮助。 - drewag

1

在Collections库中找不到Counter类型类的任何迹象。 你可以通过使用可选链略微改进代码。

func wordCount(s: String) -> Dictionary<String, Int> {
    var words = s.componentsSeparatedByString(" ")
    var wordDictionary = Dictionary<String, Int>()
    for word in words {
        if wordDictionary[word]? {
            wordDictionary[word] = wordDictionary[word]! + 1
        } else {
            wordDictionary[word] = 1
        }
    }
    return wordDictionary
}

wordCount("foo foo foo bar")

0

也许不够优雅,但实现起来很有趣

let inString = "foo foo foo bar"

func wordCount(ss: String) -> Dictionary<String, Int> {
    var dict = Dictionary<String, Int>()
    var tempString = "";var s = ss + " "
    for each in s{
        if each == " "{ if dict[tempString] {
                var tempNumber = Int(dict[tempString]!)
                dict[tempString] = Int(tempNumber+1)
                tempString = ""
            } else {dict[tempString] = 1;tempString = ""}
        } else {
            tempString += each}}
    return dict
}

println(wordCount(inString))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接