Создать массив, содержащий средневзвешенные значения других массивов - PullRequest
0 голосов
/ 20 февраля 2019

Я создаю приложение для отслеживания цен на криптовалюту, в котором есть диаграмма, иллюстрирующая стоимость портфеля за последние 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

Я уверен, что должен быть чистый способ сделать это с map и reduce, однако у меня нетеще не подумал о каких-либо потенциальных решениях.Был бы признателен даже ответ на основе цикла, поскольку я могу упростить его позже.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Если кому-то интересно, это то, чем я закончил, основываясь на ответе 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)
    }

Это требует некоторой уборки и, вероятно, может быть упрощено, но дает результат, который я искал.

0 голосов
/ 20 февраля 2019

Вы можете попробовать этот код:

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...