检查数组的所有元素在 Swift 中是否具有相同的值 [英] check if all elements of an array have the same value in Swift

查看:33
本文介绍了检查数组的所有元素在 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 结果是

<前>使用循环 9.00030136108398e-06使用包含 2.02655792236328e-06使用集合 0.0306439995765686

<小时>

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆