一尘不染

如何计算Swift数组中元素的出现次数?

swift

我已经看到了一些这样的示例,但是所有这些似乎都依赖于知道要计算发生次数的元素。我的数组是动态生成的,所以我无法知道要计算哪个元素的出现(我想计算所有元素的出现)。有人可以建议吗?

提前致谢

编辑:

也许我应该更清楚一点,数组将包含多个不同的字符串(例如 ["FOO", "FOO", "BAR", "FOOBAR"]

在不知道它们是什么的情况下,如何计算foo,bar和foobar的出现?


阅读 376

收藏
2020-07-07

共1个答案

一尘不染

Swift 3和Swift 2:

您可以使用类型的字典[String: Int]来为您的每个项目建立计数[String]

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

for item in arr {
    counts[item] = (counts[item] ?? 0) + 1
}

print(counts)  // "[BAR: 1, FOOBAR: 1, FOO: 2]"

for (key, value) in counts {
    print("\(key) occurs \(value) time(s)")
}

输出:

BAR occurs 1 time(s)
FOOBAR occurs 1 time(s)
FOO occurs 2 time(s)

斯威夫特4:

Swift 4 引入了(SE-0165)可以在字典查找中包含默认值的功能,并且可以使用诸如+=和的操作来改变结果值-=,因此:

counts[item] = (counts[item] ?? 0) + 1

变成:

counts[item, default: 0] += 1

这使得使用forEach以下命令在一条简洁的代码行中轻松进行计数操作:

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]

arr.forEach { counts[$0, default: 0] += 1 }

print(counts)  // "["FOOBAR": 1, "FOO": 2, "BAR": 1]"

斯威夫特4:reduce(into:_:)

Swift 4引入了一个新版本,reduce该版本使用inout变量来累积结果。使用它,计数的创建真正变成了一行:

let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
let counts = arr.reduce(into: [:]) { counts, word in counts[word, default: 0] += 1 }

print(counts)  // ["BAR": 1, "FOOBAR": 1, "FOO": 2]

或使用默认参数:

let counts = arr.reduce(into: [:]) { $0[$1, default: 0] += 1 }

最后,您可以将其扩展为,Array以便可以在包含Hashable项的任何数组上调用它:

extension Array where Element: Hashable {
    var histogram: [Element: Int] {
        return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
    }
}
2020-07-07