Swift中是否有一个函数可以检查数组的所有元素是否具有相同的值?就我而言,它是一个type数组Int。我知道我可以使用一个简单的for循环对其进行迭代,我只是想知道是否内置了某些东西并且速度更快。
Int
任何方法都必须遍历所有元素,直到找到另一个元素:
func allEqualUsingLoop<T : Equatable>(array : [T]) -> Bool { if let firstElem = array.first { for elem in array { if elem != firstElem { return false } } } return true }
可以使用以下contains()函数来代替显式循环:
contains()
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开始可用),并检查它是否恰好具有一个元素。
Hashable
Set
func allEqualUsingSet<T : Hashable>(array : [T]) -> Bool { let uniqueElements = Set(array) return count(uniqueElements) <= 1 }
快速基准测试显示,对于包含1,000,000个整数的数组,“包含”方法比“设置”方法快得多,尤其是在元素 不 完全相等的情况下。这是有道理的,因为contains()一旦找到不匹配的元素就返回,而Set(array)总是遍历整个数组。
Set(array)
同样,“包含”方法比显式循环同样快或稍快。
这是一些简单的基准测试代码。当然,结果可能会随数组大小,不同元素的数量和元素数据类型而变化。
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上,发布配置):
使用循环0.000651001930236816 使用包含0.000567018985748291 使用设置0.0344770550727844
随着array[1_000] = 2结果
array[1_000] = 2
使用循环9.00030136108398e-06 使用包含2.02655792236328e-06 使用设置0.0306439995765686
Swift 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