2015-04-12 144 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))} ??真的'(它更慢) –

相关问题