我有这样的字典:
let tempDict = [100:2, 101:3, 102:4]
我需要找到字典中所有元素的加权平均值。所以我基本上想要这样做
let keyMultValues = 100*2+101*3+102*4
let valTotal = 2+3+4
let final = keyMultValues/valTotal
我知道我可以遍历字典中的所有项目,但我想也许有更高效,更清洁的方法来做到这一点。
有没有比这更好的方法?
var keyMultValues = 0.0
tempDict.forEach({
keyMultValues += $0.key*$0.value
})
let valTotal = reduce(priceDict.values, 0, +) //this part isn't working properly so any help you can give here would be great. I am using swift 4
答案 0 :(得分:2)
两个观察结果:
如果您正在进行加权平均,您可能不希望进行整数计算。您可能想要浮点结果。
您可能希望避免因所有键乘以值而产生的溢出问题,然后将它们相加,然后除以值的总和。您可能希望按值执行该值:
因此:
let sumOfWeights = dictionary.reduce(0.0) { $0 + Double($1.value) }
let weightedAverage = dictionary.reduce(0.0) { $0 + Double($1.key) * Double($1.value) / sumOfWeights }
注意,这适用于原始值:
let dictionary = [100:2, 101:3, 102:4]
这也适用于大值,例如:
let dictionary = [
1_000_000_000: 20_000_000_000,
1_000_000_001: 30_000_000_000,
1_000_000_002: 40_000_000_000
]
答案 1 :(得分:0)
这个怎么样?
let keyValueProductsSum = dict.lazy.map(*).reduce(0, +)
let valueSum = dict.values.reduce(0, +)
let weightedAverage = keyValueProductsSum / valueSum
答案 2 :(得分:0)
您开始时:
var keyMultValues = 0
tempDict.forEach({
keyMultValues += $0.key*$0.value
})
let valTotal = reduce(priceDict.values, 0, +) //this part isn't working properly so any help you can give here would be great. I am using swift 4
并问:
有没有比这更好的方法?
那么你的错误就是你错误地写了reduce
,应该是:
tempDict.values.reduce(0, +)
使用此修复程序,您的代码将生成正确的(使用整数运算)结果。
但是,您的代码两个会传递数据,foreach
和reduce
(以及撰写时的其他答案执行两次或三次) )。您自己的解决方案显示您只需要执行一次传递,只需修改它以遵循valTotal
与keyMultValues
使用的相同模式:
var keyMultValues = 0
var valTotal = 0
tempDict.forEach({
let val = $0.value // we are going to use it twice
keyMultValues += $0.key * val
valTotal += val
})
let final = keyMultValues / valTotal
这只使用了一次数据传递。
如果您的数字很大,您可能需要使用“除法算法”进行两次传递,如果您希望找到浮点加权平均值,那么您需要抛出几个Double
强制转换@ Rob的回答涵盖了这两个问题。
一次传递数据真的比两个更好(更快,更少内存,无论如何)?这是一个练习!我添加了这个答案,只是为了向您展示您的原始尝试与正确解决方案的接近程度。