jjatie - 1 year ago 73

Swift Question

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`

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.

Answer Source

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()
}
}
```