简体   繁体   中英

How to get average of values in array between two given indexes in Swift

I'm trying to get the average of the values between two indexes in an array. The solution I first came to reduces the array to the required range, before taking the sum of values divided by the number of values. A simplified version looks like this:

let array = [0, 2, 4, 6, 8, 10, 12]
// The aim is to take the average of the values between array[n] and array[.count - 1].

I attempted with the following code:

 func avgOf(x: Int) throws -> String {

let avgforx = solveList.count - x

// Error handling to check if x in average of x does not overstep bounds      
        guard avgforx > 0 else {
            throw FuncError.avgNotPossible
        }

solveList.removeSubrange(ClosedRange(uncheckedBounds: (lower: 0, upper: avgforx - 1)))
        let avgx = (solveList.reduce(0, +)) / Double(x)

// Rounding
        let roundedAvgOfX = (avgx * 1000).rounded() / 1000
        print(roundedAvgOfX)
        return "\(roundedAvgOfX)"
    }

where avgforx is used to represent the lower bound :

array[(.count - 1) - x])

The guard statement makes sure that if the index is out of range, the error is handled properly.

solveList.removeSubrange was my initial solution, as it removes the values outside of the needed index range (and subsequently delivers the needed result), but this has proved to be problematic as the values not taken in the average should remain. The line in removeSubrange basically takes a needed index field (eg array[5] to array[10]), removes all the values from array[0] to array[4], and then takes the sum of the resulting array divided by the number of elements. Instead, the values in array[0] to array[4] should remain.

I would appreciate any help.

(Swift 4, Xcode 10)

Apart from the fact that the original array is modified, the error in your code is that it divides the sum of the remaining elements by the count of the removed elements ( x ) instead of dividing by the count of remaining elements.

A better approach might be to define a function which computes the average of a collection of integers:

func average<C: Collection>(of c: C) -> Double where C.Element == Int {
    precondition(!c.isEmpty, "Cannot compute average of empty collection")
    return Double(c.reduce(0, +))/Double(c.count)
}

Now you can use that with slices, without modifying the original array:

let array = [0, 2, 4, 6, 8, 10, 12]
let avg1 = average(of: array[3...])  // Average from index 3 to the end
let avg2 = average(of: array[2...4]) // Average from index 2 to 4
let avg3 = average(of: array[..<5])  // Average of first 5 elements

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM