生成包含其他数组的加权平均值的数组

时间:2019-02-19 21:57:59

标签: swift math

我正在创建一个加密货币价格跟踪应用程序,该应用程序具有一个图表来说明过去7天内投资组合的价值。因此,我需要一种在图表上生成数据点的方法。

对于投资组合中的每种加密货币,我有一个NSDecimalNumber值数组,它们表示过去一周中每小时的加密货币价格。要创建数据点,我需要一种方法来计算每小时价格的整体加权平均值。加权的意思是,总体平均数组应代表当前持有的每种加密货币的数量。

例如,如果我有以下数组:

Cryptocurrency 1 (25% of the overall portfolio value) - [1.2, 8.3, 7.2] 
Cryptocurrency 2 (25% of the overall portfolio value) - [3.4, 9.2, 6.3]
Cryptocurrency 3 (50% of the overall portfolio value) - [6.3, 1.1, 5.9]

结果应为:

[4.3, 4.92, 6.33]

计算的结果:

((1.2 * 0.75) + (3.4 * 0.75) + (6.3 * 1.5)) / 3 = 4.3
((8.3 * 0.75) + (9.2 * 0.75) + (1.1 * 1.5)) / 3 = 4.92
((7.2 * 0.75) + (6.3 * 0.75) + (5.9 * 1.5)) / 3 = 6.33

我敢肯定必须使用mapreduce来做到这一点,但是我还没有想到任何可能的解决方案。甚至基于循环的答案也将不胜感激,因为我以后可以简化它。

2 个答案:

答案 0 :(得分:1)

您可以尝试以下代码:

    let weight = [0.25, 0.25, 0.5]// Weights of your crypto, matrix 1*N
    let crypto1 = [1.2, 8.3, 7.2]
    let crypto2 = [3.4, 9.2, 6.3]
    let crypto3 = [6.3, 1.1, 5.9]
    let crypto = [crypto1, crypto2, crypto3]// Matrix M*N

    var result: [Double] = []
    for i in 0..<weight.count {
        let aux = crypto.map { $0[i] }
        let sum = zip(aux, weight).map { $0 * $1 }.reduce(0,+)
        result.append(sum)
    }
    print("test: \(result)")  // print "test: [4.3, 4.925, 6.325]"

希望这会有所帮助。

答案 1 :(得分:0)

如果有人好奇,这就是我根据qtngo的答案得出的结论:

    let holdings = cryptocurrencies.flatMap { cryptocurrency -> (cryptocurrency: Cryptocurrency, assetHolding: AssetHolding)? in
        guard let assetHolding = portfolio.assetHolding(forCryptocurrency: cryptocurrency) else {
            return nil
        }
        return (cryptocurrency, assetHolding)
    }
    let sparklineLength = holdings.map { $0.cryptocurrency.marketOverview.sparkline.count }.min() ?? 0
    let weights = holdings.flatMap { holding -> NSDecimalNumber in
        let quantity = NSDecimalNumber(value: holding.assetHolding.quantity)
        let value = holding.cryptocurrency.marketOverview.valuation.value
        let totalHoldingValue = value.multiplying(by: quantity)
        let totalPortfolioValue = portfolio.totalValue(withCryptocurrencies: cryptocurrencies)
        let percentage = totalHoldingValue.dividing(by: totalPortfolioValue)
        return percentage
    }

    var averageSparkline = [NSDecimalNumber]()
    for index in 0..<sparklineLength {
        let indexSparklineValues = holdings.flatMap { holding -> NSDecimalNumber? in
            return holding.cryptocurrency.marketOverview.sparkline[index]
        }
        let averageSparklineValue = zip(indexSparklineValues, weights).map { $0.multiplying(by: $1) }.reduce(0, +)
        averageSparkline.append(averageSparklineValue)
    }

它需要整理一下,可能可以简化,但是可以产生我一直在寻找的结果。