arraysfunctionswiftswift-playground

# Making my function calculate average of array Swift

I want my function to calculate the average of my Double type array. The array is called "votes". For now, I have 10 numbers.

When I call the `average function` to get the average of the array votes, it doesn't work.

Here's my code:

``````var votes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

func average(nums: Double...) -> Double {
var total = 0.0
total += vote
}
return average
}

``````

How do I call the average here to get the average?

Solution

• You should use the `reduce` method to sum your sequence elements as follow:

Xcode Xcode 10.2+ • Swift 5 or later

``````extension Sequence where Element: AdditiveArithmetic {
/// Returns the total sum of all elements in the sequence
func sum() -> Element { reduce(.zero, +) }
}
``````

``````extension Collection where Element: BinaryInteger {
/// Returns the average of all elements in the array
func average() -> Element { isEmpty ? .zero : sum() / Element(count) }
/// Returns the average of all elements in the array as Floating Point type
func average<T: FloatingPoint>() -> T { isEmpty ? .zero : T(sum()) / T(count) }
}
``````

``````extension Collection where Element: BinaryFloatingPoint {
/// Returns the average of all elements in the array
func average() -> Element { isEmpty ? .zero : sum() / Element(count) }
}
``````

``````let votes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
``````

If you need to work with `Decimal` types its total sum it is already covered by the `AdditiveArithmetic` protocol extension method, so you only need to implement the average:

``````extension Collection where Element == Decimal {
func average() -> Decimal { isEmpty ? .zero : sum() / Decimal(count) }
}
``````

If you need to sum a certain property of a custom structure we can extend `Sequence` and create a method that takes a KeyPath as argument to calculate its sum:

``````extension Sequence  {
func sum<T: AdditiveArithmetic>(_ predicate: (Element) -> T) -> T {
reduce(.zero) { \$0 + predicate(\$1) }
}
}
``````

Usage:

``````struct User {
let name: String
let age: Int
}

let users: [User] = [
.init(name: "Steve", age: 45),
.init(name: "Tim", age: 50)]

let ageSum = users.sum(\.age) // 95
``````

And extend collection to calculate its average:

``````extension Collection {
func average<T: BinaryInteger>(_ predicate: (Element) -> T) -> T {
sum(predicate) / T(count)
}
func average<T: BinaryInteger, F: BinaryFloatingPoint>(_ predicate: (Element) -> T) -> F {
F(sum(predicate)) / F(count)
}
func average<T: BinaryFloatingPoint>(_ predicate: (Element) -> T) -> T {
sum(predicate) / T(count)
}
func average(_ predicate: (Element) -> Decimal) -> Decimal {
sum(predicate) / Decimal(count)
}
}
``````

Usage:

``````let ageAvg = users.average(\.age)                 // 47
let ageAvgDouble: Double = users.average(\.age)   // 47.5
``````