/ 猿问

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

2019-09-21 15:42:39

## 3 回答

Swift 3和Swift 2：

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)

Swift 4 引入了（SE-0165）可以在字典查找中包含默认值的功能，并且可以使用诸如+=和的操作对结果值进行突变-=，因此：

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

counts[item, default: 0] += 1

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]"

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 }

extension Array where Element: Hashable {

var histogram: [Element: Int] {

return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }

}

}

＃1。使用Array的reduce(into:_:)和Dictionary的subscript(_:default:)标

let array = [4, 23, 97, 97, 97, 23]

let dictionary = array.reduce(into: [:]) { counts, number in

counts[number, default: 0] += 1

}

print(dictionary) // [4: 1, 23: 2, 97: 3]

＃2。使用repeatElement(_:count:)函数，zip(_:_:)函数和Dictionary的init(_:uniquingKeysWith:)初始值设定项

let array = [4, 23, 97, 97, 97, 23]

let repeated = repeatElement(1, count: array.count)

//let repeated = Array(repeating: 1, count: array.count) // also works

let zipSequence = zip(array, repeated)

let dictionary = Dictionary(zipSequence, uniquingKeysWith: { (current, new) in

return current + new

})

//let dictionary = Dictionary(zipSequence, uniquingKeysWith: +) // also works

print(dictionary) // prints [4: 1, 23: 2, 97: 3]

＃3。使用Dictionary的init(grouping:by:)初始值设定项和mapValues(_:)方法

let array = [4, 23, 97, 97, 97, 23]

let dictionary = Dictionary(grouping: array, by: { \$0 })

let newDictionary = dictionary.mapValues { (value: [Int]) in

return value.count

}

print(newDictionary) // prints: [97: 3, 23: 2, 4: 1]

＃4。使用Dictionary的init(grouping:by:)初始值设定项和map(_:)方法

let array = [4, 23, 97, 97, 97, 23]

let dictionary = Dictionary(grouping: array, by: { \$0 })

let newArray = dictionary.map { (key: Int, value: [Int]) in

return (key, value.count)

}

print(newArray) // prints: [(4, 1), (23, 2), (97, 3)]

＃5。使用for循环和Dictionary的subscript(_:)下标

extension Array where Element: Hashable {

func countForElements() -> [Element: Int] {

var counts = [Element: Int]()

for element in self {

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

}

return counts

}

}

let array = [4, 23, 97, 97, 97, 23]

print(array.countForElements()) // prints [4: 1, 23: 2, 97: 3]

＃6。使用NSCountedSet和NSEnumerator的map(_:)方法（需要Foundation）

import Foundation

extension Array where Element: Hashable {

func countForElements() -> [(Element, Int)] {

let countedSet = NSCountedSet(array: self)

let res = countedSet.objectEnumerator().map { (object: Any) -> (Element, Int) in

return (object as! Element, countedSet.count(for: object))

}

return res

}

}

let array = [4, 23, 97, 97, 97, 23]

print(array.countForElements()) // prints [(97, 3), (4, 1), (23, 2)]

＃7。使用NSCountedSet和AnyIterator（需要Foundation）

import Foundation

extension Array where Element: Hashable {

func counForElements() -> Array<(Element, Int)> {

let countedSet = NSCountedSet(array: self)

var countedSetIterator = countedSet.objectEnumerator().makeIterator()

let anyIterator = AnyIterator<(Element, Int)> {

guard let element = countedSetIterator.next() as? Element else { return nil }

return (element, countedSet.count(for: element))

}

return Array<(Element, Int)>(anyIterator)

}

}

let array = [4, 23, 97, 97, 97, 23]

print(array.counForElements()) // [(97, 3), (4, 1), (23, 2)]

14/04/14我将此代码更新为Swift2.2

16/10/11更新为Swift3

extension Sequence where Self.Iterator.Element: Hashable {

private typealias Element = Self.Iterator.Element

func freq() -> [Element: Int] {

return reduce([:]) { (accu: [Element: Int], element) in

var accu = accu

accu[element] = accu[element]?.advanced(by: 1) ?? 1

return accu

}

}

}

Equatable：

extension Sequence where Self.Iterator.Element: Equatable {

private typealias Element = Self.Iterator.Element

func freqTuple() -> [(element: Element, count: Int)] {

let empty: [(Element, Int)] = []

return reduce(empty) { (accu: [(Element, Int)], element) in

var accu = accu

for (index, value) in accu.enumerated() {

if value.0 == element {

accu[index].1 += 1

return accu

}

}

return accu + [(element, 1)]

}

}

}

let arr = ["a", "a", "a", "a", "b", "b", "c"]

print(arr.freq()) // ["b": 2, "a": 4, "c": 1]

print(arr.freqTuple()) // [("a", 4), ("b", 2), ("c", 1)]

for (k, v) in arr.freq() {

print("\(k) -> \(v) time(s)")

}

// b -> 2 time(s)

// a -> 4 time(s)

// c -> 1 time(s)

for (element, count) in arr.freqTuple() {

print("\(element) -> \(count) time(s)")

}

// a -> 4 time(s)

// b -> 2 time(s)

// c -> 1 time(s)

• 3 回答
• 0 关注
• 328 浏览

0/150