我有一系列双打数组。例如:
let mceGain = [[3,4,5],[7,4,3],[12,10,7]] // Written as integers for simplicity here
我现在想要使用相应的索引来平均不同数组中的元素。所以我的输出看起来有点像这样:
//firstAvg: (3+7+12)/3 = 7.33
//secondAvg: (4+4+10)/3 = 6
//thirdAvg: (5+3+7)/3 = 5
最后我想将这些平均值存储在一个更简单的数组中:
//mceGain: [7.33,6,5]
我试过用一个带有switch语句的双for循环来做到这一点,但这似乎是不必要的复杂。我假设使用reduce()
,map()
和filter()
的组合可以实现相同的结果,但我似乎无法绕过它。
答案 0 :(得分:2)
让我们来分析一下你想做什么。您从一组数组开始:
[[3,4,5],[7,4,3],[12,10,7]]
并且您希望将每个子数组转换为数字:
[7,6,5]
每当您将此序列的“每个元素转换为其他元素”时,请使用map
。
计算平均值时,需要将一系列事物转换为一个事物。这意味着我们需要reduce
。
let array: [[Double]] = [[3,4,5],[7,4,3],[12,10,7]]
let result = array.map { $0.reduce(0.0, { $0 + $1 }) / Double($0.count) }
评论:
let array: [[Double]] = [[3,4,5],[7,4,3],[12,10,7]]
let result = array.map { // transform each element like this:
$0.reduce(0.0, { $0 + $1 }) // sums everything in the sub array up
/ Double($0.count) } // divide by count
编辑:
您需要做的是首先“转置”数组,然后执行地图并减少:
array[0].indices.map{ index in // these three lines makes the array [[3, 7, 12], [4, 4, 10], [5, 3, 7]]
array.map{ $0[index] }
}
.map { $0.reduce(0.0, { $0 + $1 }) / Double($0.count) }
答案 1 :(得分:1)
这应该回答你的评论
let elms: [[Double]] = [[3, 5, 3], [4, 4, 10] , [5, 3, 7]]
func averageByIndex(elms:[[Double]]) -> [Double]? {
guard let length = elms.first?.count else { return []}
// check all the elements have the same length, otherwise returns nil
guard !elms.contains(where:{ $0.count != length }) else { return nil }
return (0..<length).map { index in
let sum = elms.map { $0[index] }.reduce(0, +)
return sum / Double(elms.count)
}
}
if let averages = averageByIndex(elms: elms) {
print(averages) // [4.0, 4.0, 6.666666666666667]
}