检查数组的所有元素在 Swift 中是否具有相同的值 [英] check if all elements of an array have the same value in Swift
问题描述
Swift 中是否有一个函数可以检查数组的所有元素是否具有相同的值?在我的例子中,它是一个 Int
类型的数组.我知道我可以使用一个简单的 for 循环来迭代它,我只是想知道是否有内置的更快的东西.
任何方法都必须遍历所有元素,直到找到不同的元素:
func allEqualUsingLoop(array : [T]) ->布尔{如果让 firstElem = array.first {对于数组中的元素{如果 elem != firstElem {返回假}}}返回真}
您可以使用 contains()
函数代替显式循环:
func allEqualUsingContains(array : [T]) ->布尔{如果让 firstElem = array.first {返回 !contains(array, { $0 != firstElem })}返回真}
如果数组元素是Hashable
(比如Int
),那么你可以从数组元素创建一个 Set
(自 Swift 1.2 起可用)并检查它是否只有一个元素.
func allEqualUsingSet(array : [T]) ->布尔{让 uniqueElements = Set(array)返回计数(唯一元素)<= 1}
一个快速的基准测试显示contains"方法比set"方法快得多对于 1,000,000 个整数的数组,特别是如果元素是并非都是平等的.这是有道理的,因为 contains()
会尽快返回当找到不匹配的元素时,而 Set(array)
总是遍历整个数组.
此外,包含"方法与显式循环一样快或略快.
这是一些简单的基准测试代码.当然结果可能会有所不同与数组大小、不同元素的数量和元素数据类型.
func measureExecutionTime(title: String, @noescape f : (() -> T) ) ->T{让开始 = NSDate()让结果 = f()让结束 = NSDate()让持续时间 = end.timeIntervalSinceDate(start)println("\(title) \(duration)")返回结果}var array = [Int](计数:1_000_000,重复值:1)数组[500_000] = 2让 b1 = measureExecutionTime("使用循环") {返回 allEqualUsingLoop(array)}让 b2 = measureExecutionTime(使用包含"){allEqualUsingContains(数组)}让 b3 = measureExecutionTime("使用集合") {allEqualUsingSet(数组)}
结果(在 MacBook Pro 上,发布配置):
<前>使用循环 0.000651001930236816使用包含 0.000567018985748291使用集合 0.0344770550727844使用 array[1_000] = 2
结果是
<小时>
Swift 2/Xcode 7 的更新: 由于 Swift 中的各种变化语法,函数现在写成
func allEqual(array : [T]) ->布尔{如果让 firstElem = array.first {返回 !array.dropFirst().contains { $0 != firstElem }}返回真}
但你现在也可以将其定义为数组的扩展方法:
extension Array where Element : Equatable {func allEqual() ->布尔{如果让 firstElem = first {返回 !dropFirst().contains { $0 != firstElem }}返回真}}打印([1, 1, 1].allEqual())//真打印([1, 2, 1].allEqual())//假
Is there a function in Swift that checks whether all elements of an array have the same value? In my case, it's an array of type Int
. I know I can iterate over it using a simple for loop I was just wondering if there is something that is built in and quicker.
Any method must iterate over all elements until a different element is found:
func allEqualUsingLoop<T : Equatable>(array : [T]) -> Bool {
if let firstElem = array.first {
for elem in array {
if elem != firstElem {
return false
}
}
}
return true
}
Instead of an explicit loop you can use the contains()
function:
func allEqualUsingContains<T : Equatable>(array : [T]) -> Bool {
if let firstElem = array.first {
return !contains(array, { $0 != firstElem })
}
return true
}
If the array elements are Hashable
(such as Int
) then you can
create a Set
(available since Swift 1.2) from the array elements and check if it has exactly one element.
func allEqualUsingSet<T : Hashable>(array : [T]) -> Bool {
let uniqueElements = Set(array)
return count(uniqueElements) <= 1
}
A quick benchmarking test revealed that the "contains" method is much faster than the "set" method
for an array of 1,000,000 integers, in particular if the elements are
not all equal. This make sense because contains()
returns as soon
as a non-matching element is found, whereas Set(array)
always
traverses the entire array.
Also the "contains" methods is equally fast or slightly faster than an explicit loop.
Here is some simple benchmarking code. Of course the results can vary with the array size, the number of different elements and the elements data type.
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)
}
Results (on a MacBook Pro, Release configuration):
using loop 0.000651001930236816 using contains 0.000567018985748291 using set 0.0344770550727844
With array[1_000] = 2
the results are
using loop 9.00030136108398e-06 using contains 2.02655792236328e-06 using set 0.0306439995765686
Update for Swift 2/Xcode 7: Due to various changes in the Swift syntax, the function is now written as
func allEqual<T : Equatable>(array : [T]) -> Bool {
if let firstElem = array.first {
return !array.dropFirst().contains { $0 != firstElem }
}
return true
}
But you can now also define it as an extension method for arrays:
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
这篇关于检查数组的所有元素在 Swift 中是否具有相同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!