i have an array, var hoursPlayed = String they are in a tableView and are all numbers, how would i add the numbers in that array together to get the average of hours played????? in Swift 2
4 Answers
You could use reduce:
let sum= hoursPlayed.reduce(0.0,combine:{$0+Float($1)!})
Basically you are iterating through the array and accumulating all the values. Since it is an array of strings,for simplicity I've force unwrapped to a Float, but you must check for the optional. The reduce function takes a closure as argument with 2 parameters. The dollar sign means take the first and the second and sum them.
Now you can easily divide to the number of elements in the array to have an avergae.
If you are in objC world it would be nice use key value coding and the @avg operator.
[UPDATE]
As Darko posted out the first version won't compile. The error was converting the first argument to a Float, since reduce takes an initial value and I put it as Float there is no need for further conversion.
let array = ["10.0", "30.0"]
if array.count > 0 {
let average = array.reduce(0.0, combine: {$0 + (Double($1) ?? 0.0)}) / Double(array.count)
print(average) // 20.0
}
$0 does not need to be converted because it is guaranteed that it's always Double. $0 is inferred from the initial value, which is declared as 0.0: Double.
array.count has to be checked to guard against a division thru 0.
1 Comment
?? is much better than forced unwrapping. Nicely done. (Comment should be changed to 20.0, though, as you correctly produce a Double not a String.)I'd use a combination of flatMap to convert the strings to Doubles and reduce to add them up:
let doubles = array.flatMap { Double($0) }
let average = doubles.reduce(0.0, combine:+) / Double(doubles.count)
Using flatMap protects you from entries in array that can't be converted to Double If you know they all convert you can simplify it to:
let average = array.map({ Double($0)! }) / Double(array.count)
One final option is to extend Array with an average function if that seems like something you'll be more generally using, and use it in combination with flatMap and/or map:
protocol ArithmeticType {
static func zero() -> Self
func +(lhs:Self, rhs:Self) -> Self
func -(lhs:Self, rhs:Self) -> Self
func /(lhs:Self, rhs:Self) -> Self
func *(lhs:Self, rhs:Self) -> Self
init(_ number:Int)
}
extension Double : ArithmeticType {
static func zero() -> Double {
return 0.0
}
}
extension Array where Element : ArithmeticType {
func average() -> Element {
return reduce(Element.zero(), combine:+) / Element(count)
}
}
let avg = array.flatMap { Double($0) }.average()
2 Comments
Modified Darko's approach, which take in account if String is convertible to Double, or not. For an empty array it returns 0.0
let array = ["10.0", "31.2", "unknown", ""]
func avg(arr: [String])->Double {
let arr = array.flatMap(Double.init)
var avg = 0.0
if arr.count > 0 {
avg = arr.reduce(0.0, combine: + ) / Double(arr.count)
}
return avg
}
let a = avg(array)
print(a) // 20.6