jjatie - 4 months ago 26
Swift Question

# Sample variation for an array of Int in Swift

Building on this question, I am trying to calculate the variance of an array of Int.

My extension looks like this so far:

``````extension Array where Element: Integer {
/// Returns the sum of all elements in the array
var total: Element {
return reduce(0, combine: +)
}
/// Returns the average of all elements in the array
var average: Double {
return isEmpty ? 0 : Double(total.hashValue) / Double(count)
}

/// Returns an array of the squared deviations from the mean
var squaredDeviations: [Double] {
let mean = average
return isEmpty ? 0 : map( { number in
let difference = Double(number) - mean
return pow(distance, 2)
})
}
}
``````

Total and average work fine, but for squaredDifferences it appears that you must return the same type as the array when using
`map`
. Is there a way to get around this?

Update I was receiving the compiler error:

Result values in '? :" expression have mismatching types 'Int' and
'[ _ ]'

The problem was that I was returning 0 which is not an array of Doubles. Also I was not using number.hashValue, and therefor couldn't initialize the double.

The issue here is that you have two possible values that can be returned:

``````return isEmpty ? 0 : map( { number in
let difference = Double(number) - mean
return pow(distance, 2)
})
``````

Lets break these `conditional` operator down into `if`/`else`:

``````if isEmpty {
return 0 //inferred return type: Int
}
else {
return map( { number in
let difference = Double(number) - mean
return pow(distance, 2)
}) // inferred return type: [Double]
}
``````

The two possible returns have different types.

Variance is the the average of the squared differences from the Mean. You forgot to do the averaging step. Try:

``````var squaredDeviations: Double {
let mean = average
return isEmpty ? 0.0 : self.map{ pow(Double(\$0) - mean, 2) }.average
}
``````

On a side note: I would recommend against using computed properties to do expensive computations. It's presents a misleading API that doesn't make it clear that it's a slow, linear time, procedure. Here's how I would do this:

``````extension Array where Element: Integer {
/// Returns the sum of all elements in the array
func summed() -> Element {
return self.reduce(0, combine: +)
}

/// Returns the average of all elements in the array
var averaged() Double {
return self.isEmpty ? 0 : Double(self.summed()) / Double(count)
}

/// Returns an array of the squared deviations from the mean
func squaredDeviations() -> [Double] {
let average = self.averaged()
return isEmpty ? [] : map{ pow(Double(\$0) - average, 2)}
}

/// Returns the variance of the Array
func variance() -> Double {
return self.squaredDeviations().averaged()
}
}
``````