Reputation: 339
We have an array, for example:
let numbers = [-1.0,1.0,3.0,4.0,-1.0,-2.0,2.0]
We know how to get maximum consecutive positive number:
let pos = numbers.map({ () -> (Double) -> Int in var c = 0; return { c = $0 > 0 ? c + 1 : 0; return c } }())
// [0, 1, 2, 3, 0, 0, 1]
let maxConsecutivePos = pos.max()!
//3
How can we find average consecutive positive number the same way, using closures and pos array in our case? For this example, we divide sum (3 + 1) by 2 -> 2 is expected output.
Upvotes: 2
Views: 259
Reputation: 3278
You basically compare each element with the next one and check, if it the next one is less. If it is less, then it's a max and you use it to calculate the average.
let array = [0, 1, 2, 3, 0, 0, 1]
func maxConsAvg(array: [Int]) -> Double? {
guard array.count > 1 else {
return array.first.flatMap({ Double($0) })
}
let array = array + [0]
let maxs = zip(array.dropLast(), array.dropFirst())
.flatMap { (first, second) -> Int? in
return first > second ? first : nil
} //[3, 1]
return Double(maxs.reduce(0, +)) / Double(maxs.count)
}
maxConsAvg(array: array) //2
Upvotes: 1
Reputation: 539965
A possible solution: Split the array into slices of consecutive positive numbers, then compute the average slice length:
let numbers = [-1.0, 1.0, 3.0, 4.0, -1.0, -2.0, 2.0]
let slices = numbers.split(whereSeparator: { $0 <= 0 })
// --> [ArraySlice([1.0, 3.0, 4.0]), ArraySlice([2.0])]
let avg = Double(slices.reduce(0, { $0 + $1.count })) / Double(slices.count)
print(avg) // 2.0
Upvotes: 6