2016-07-06 13 views
0

Aufbauend auf diesem question, ich versuche, die Varianz eines Arrays von Int zu berechnen.Beispielvariation für ein Array von Int in Swift

Meine Erweiterung sieht wie folgt aus so weit:

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

Gesamt und durchschnittliche Arbeit in Ordnung, aber für squaredDifferences scheint es, dass Sie den gleichen Typ wie das Array zurückgeben muss, wenn map verwenden. Gibt es eine Möglichkeit, dies zu umgehen?

aktualisiert I den Compiler-Fehler erhielt:

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

Das Problem war, dass I 0 zurückkehren, das nicht eine Reihe von Doubles ist. Außerdem habe ich number.hashValue nicht verwendet und konnte daher das Double nicht initialisieren.

+0

't scheint, dass Sie den gleichen Typ wie das Array bei der Verwendung von map zurückgeben müssen" Nicht wahr, Karte existiert hauptsächlich um nur zu erleichtern, die Konvertierung zwischen den Typen. – Alexander

+0

"Es scheint, dass Sie den gleichen Typ wie das Array zurückgeben müssen, wenn Sie map verwenden" Nein, es gibt keine solche Regel. Sie können einen beliebigen Typ aus Ihrer 'map' -Funktion zurückgeben. Und tatsächlich tust du das: eine ganze Zahl kommt herein und ein Doppel kommt heraus. Ist das dein echter Code ??? Was genau ist das Problem? – matt

+3

Das Problem ist, dass, wenn das Array leer ist, Sie versuchen, "0" zurückzugeben, die kein Array von Double ist. – Eduardo

Antwort

1

Die Ausgabe hier ist, dass man zwei mögliche Werte, die zurückgegeben werden können:

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

Lets brechen diese conditional Betreiber nach unten in 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] 
} 

Die beiden möglichen Renditen unterschiedlich haben Arten.

Variance ist die durchschnittlichen der squared Differenzen von dem Mittelwert. Sie haben vergessen, den Mittelungsschritt durchzuführen. Versuchen Sie:

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

Auf einer Randnotiz: Ich würde gegen die Verwendung von berechneten Eigenschaften, um teure Berechnungen zu tun empfehlen. Es stellt eine irreführende API dar, die nicht klarstellt, dass es sich um eine langsame, lineare Zeitprozedur handelt. Hier ist, wie ich das tun würde:

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 
    func 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() 
    } 
} 
+0

Danke. Ich wollte die Varianz als separate Variable ausbrechen, da ich nur auf die quadratischen Abweichungen vom Mittelwert zugreifen möchte. – jjatie

+0

Oh, ich verstehe. Ich werde das schnell schlagen – Alexander

+1

Siehe meine Bearbeitung. Ich würde berechnete Eigenschaften für teure Berechnungen vermeiden – Alexander