2015-04-12 127 views

回答

21

任何方法必須遍歷所有元素,直到一個不同的元素被發現:

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

而是外在的循環,你可以使用功能:

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

如果數組元素是Hashable (如Int),那麼你可以 從數組元素中創建一個Set(從Swift 1.2開始可用),並檢查它是否只有一個元素。

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

快速基準測試表明,「包含」方法比「置位」方法 快得多爲百萬個整數的數組,特別是如果元件是 全部相等。這是有意義的,因爲儘快返回 作爲找到的不匹配元素,而Set(array)總是 遍歷整個數組。

此外,「contains」方法與顯式循環同樣快或略快。

這是一些簡單的基準測試代碼。當然結果可以變化 與數組大小,不同元素的數量和元素數據類型。

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

結果(在MacBook Pro上,推出配置):

 
using loop  0.000651001930236816 
using contains 0.000567018985748291 
using set  0.0344770550727844 

隨着array[1_000] = 2結果是

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

更新夫特2/Xcode中7:由於Swift 語法的各種更改,該功能現在寫成

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

但你現在也可以將它定義爲數組的擴展方法:

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

試圖同...編譯器檢查;-) – Antonio

+0

@Antonio:好,謝謝! –

+0

如果你有興趣試試另一個,你可以使用'equal'和'Repeat':'array.first.map {equal(array,Repeat(count:array.count,repeatedValue:$ 0))} ??真的'(它更慢) –

相關問題