我正在尝试实现groupBy功能,其中嵌套列表的所有数字都被分组。到目前为止我的代码:
struct MyClass {
var numbers: [Int]
...
}
var dict: [String : MyClass] = ...
let numbers = dict
.filter{ $0.0.containsString(searchString) }
.flatMap{ $0.1.numbers }
这会产生Array
Int
秒。但是我想要一个字典[Int:Int],每个唯一的数字和它的出现次数。例如:
[1,2,3,4,1,2,2,1]
应该是:
[1 : 2, 2 : 3, 3 : 1, 4 : 1]
我知道有groupBy
运算符,但Swift似乎没有运算符。我试过reduce
:
func reducer(accumulator: [Int: Int], num: Int) -> [Int : Int] {
var acc = accumulator
acc[num]! += 1
return acc
}
filtered.reduce([:], combine: reducer)
但是当我想要运行它时崩溃了。不知道为什么,我得到一个EXC_BAD_INSTRUCTION。
我很感激任何帮助。
答案 0 :(得分:3)
我希望崩溃发生在这条线上:
acc[num]! += 1
第一次调用此数字时,该字词在字典中不存在,因此acc[num]
为nil
。强行打开它会导致崩溃。
不确定这是否是最佳解决方案,但您可以简单地检查这种情况:
if (acc[num]) {
acc[num]! += 1
} else {
acc[num] = 1
}
评论中来自@vacawama的清洁代码:
acc[num] = (acc[num] ?? 0) + 1
答案 1 :(得分:3)
let numbers = [1,2,3,4,1,2,2,1]
var results = [Int: Int]()
Set(numbers).forEach { number in results[number] = numbers.filter { $0 == number }.count }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
其实我不太确定这是不是你想要的。我只看了你的例子。
使用NSCountedSet
:
var objects = [1,2,3,4,1,2,2,1]
let uniques = NSCountedSet(array: objects)
uniques.forEach { results[$0 as! Int] = uniques.countForObject($0) }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
答案 2 :(得分:2)
这是Array的扩展,可以满足您的要求:
extension Array where Element: Hashable {
var grouped: [Element:Int] {
var dict = [Element:Int]()
self.forEach { dict[$0] = (dict[$0] ?? 0) + 1 }
return dict
}
}
关键是闭包:{ dict[$0] = (dict[$0] ?? 0) + 1 }
。
它接受数组中的当前值,测试它是否是字典中的键,如果存在则返回该键的值,如果不存在,则返回0,然后添加一个并设置关键:值为当前值和当前事件的对。
使用示例:
[1,2,3,4,1,2,2,1].grouped // => [2: 3, 3: 1, 1: 3, 4: 1]
答案 3 :(得分:0)
你需要这样的东西:
if let _ = acc.indexForKey(num) {
acc[num]! += 1
}
else {
acc[num] = 1
}
答案 4 :(得分:0)
它有点不清楚你要求的是什么,但这里有一个函数,它将采用一系列的int并返回一个以数字为键的字典,并将计数作为值:
func getDictionaryOfCounts(accumulator: [Int]) -> [Int : Int] {
var countingDictionary: [Int : Int] = [:]
accumulator.forEach { (value) in
if countingDictionary[value] != nil {
countingDictionary[value]! += 1
}
else{
countingDictionary[value] = 1
}
}
return countingDictionary
}