加权字典中元素的平均值

时间:2017-12-21 22:44:21

标签: swift swift4

我有这样的字典:

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

3 个答案:

答案 0 :(得分:2)

两个观察结果:

  1. 如果您正在进行加权平均,您可能不希望进行整数计算。您可能想要浮点结果。

  2. 您可能希望避免因所有键乘以值而产生的溢出问题,然后将它们相加,然后除以值的总和。您可能希望按值执行该值:

  3. 因此:

    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, +)

使用此修复程序,您的代码将生成正确的(使用整数运算)结果。

但是,您的代码两个会传递数据,foreachreduce(以及撰写时的其他答案执行两次或三次) )。您自己的解决方案显示您只需要执行一次传递,只需修改它以遵循valTotalkeyMultValues使用的相同模式:

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的回答涵盖了这两个问题。

一次传递数据真的比两个更好(更快,更少内存,无论如何)?这是一个练习!我添加了这个答案,只是为了向您展示您的原始尝试与正确解决方案的接近程度。