2015-04-12 10 views

Antwort

21

Jedes Verfahren iterieren müssen alle Elemente, bis ein anderes Element gefunden wird:

func allEqualUsingLoop<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     for elem in array { 
      if elem != firstElem { 
       return false 
      } 
     } 
    } 
    return true 
} 

Statt einer expliziten Schleife Sie die Funktion verwenden können:

func allEqualUsingContains<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     return !contains(array, { $0 != firstElem }) 
    } 
    return true 
} 

Wenn die Array-Elemente Hashable sind (wie Int) dann können Sie ein Set (verfügbar seit Swift 1.2) von den Array-Elementen erstellen und überprüfen, ob es genau ein Element hat.

func allEqualUsingSet<T : Hashable>(array : [T]) -> Bool { 
    let uniqueElements = Set(array) 
    return count(uniqueElements) <= 1 
} 

Ein schneller Benchmarking-Test ergab, dass die „enthält“ Verfahren viel schneller als die „set“ -Methode ist für eine Reihe von 1.000.000 ganzen Zahlen, insbesondere wenn die Elemente nicht alle gleich sind. Dies ergibt einen Sinn, da so bald zurückgibt, wie ein nicht übereinstimmendes Element gefunden wird, während Set(array) immer das gesamte Array durchläuft.

Auch die "enthält" -Methoden ist genauso schnell oder etwas schneller als eine explizite Schleife.

Hier ist ein einfacher Benchmark-Code. Natürlich können die Ergebnisse mit der Array-Größe, der Anzahl der verschiedenen Elemente und dem Datentyp der Elemente variieren.

func measureExecutionTime<T>(title: String, @noescape f : (() -> T)) -> T { 
    let start = NSDate() 
    let result = f() 
    let end = NSDate() 
    let duration = end.timeIntervalSinceDate(start) 
    println("\(title) \(duration)") 
    return result 
} 

var array = [Int](count: 1_000_000, repeatedValue: 1) 
array[500_000] = 2 

let b1 = measureExecutionTime("using loop ") { 
    return allEqualUsingLoop(array) 
} 

let b2 = measureExecutionTime("using contains") { 
    allEqualUsingContains(array) 
} 

let b3 = measureExecutionTime("using set  ") { 
    allEqualUsingSet(array) 
} 

Ergebnisse (auf einem MacBook Pro, Release-Konfiguration):

 
using loop  0.000651001930236816 
using contains 0.000567018985748291 
using set  0.0344770550727844 

Mit array[1_000] = 2 die Ergebnisse sind

 
using loop  9.00030136108398e-06 
using contains 2.02655792236328e-06 
using set  0.0306439995765686 

Update für Swift 2/Xcode 7: Aufgrund verschiedener Änderungen in der Swift Syntax Wird die Funktion nun als

func allEqual<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     return !array.dropFirst().contains { $0 != firstElem } 
    } 
    return true 
} 

geschrieben Aber man kann jetzt auch als Erweiterung Methode für Arrays definieren:

extension Array where Element : Equatable { 
    func allEqual() -> Bool { 
     if let firstElem = first { 
      return !dropFirst().contains { $0 != firstElem } 
     } 
     return true 
    } 
} 

print([1, 1, 1].allEqual()) // true 
print([1, 2, 1].allEqual()) // false 
+0

Versuchen die gleiche ... Compiler überprüft ;-) – Antonio

+0

@Antonio: OK danke! –

+0

Wenn Sie an einem anderen interessiert sind, können Sie 'equal' und' Repeat' verwenden: 'array.first.map {equal (array, Wiederholung (count: array.count, repeatedValue: $ 0))} ?? true' (es ist langsamer) –

Verwandte Themen