检查数组中的所有元素是否在Swift中具有相同的值

时间:2015-04-12 09:56:58

标签: arrays swift

Swift中是否有一个函数检查数组的所有元素是否具有相同的值?在我的例子中,它是Int类型的数组。我知道我可以使用一个简单的for循环迭代它我只是想知道是否有内置和更快的东西。

3 个答案:

答案 0 :(得分:32)

任何方法都必须迭代所有元素,直到找到不同的元素:

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

您可以使用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起可用)并检查它是否只有一个元素。

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

快速基准测试显示&#34;包含&#34;方法比&#34; set&#34;快得多。方法 对于1,000,000个整数的数组,特别是如果元素是 都是平等的。这是有道理的,因为contains()会尽快返回 找到一个非匹配元素,而Set(array)总是如此 遍历整个数组。

&#34;还包含&#34;方法与显式循环同样快或稍快。

这是一些简单的基准测试代码。当然结果可能会有所不同 与数组大小,不同元素的数量和元素数据类型。

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

更新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

答案 1 :(得分:10)

Swift 4.2 / Xcode 10的解决方案:

ArraySlice

如果您当前的Xcode版本高于10.0,则可以在Xcode9to10Preparation中找到$的{​​{1}}函数。您可以使用CocoaPods安装此库。

答案 2 :(得分:2)

使用Swift 5,您可以使用以下四种方法之一来测试数组的所有元素是否相等。


#1。使用Array的{​​{3}}方法

allSatisfy(_:)返回一个布尔值,该布尔值指示序列中的每个元素是否满足给定谓词。您可以设置谓词以测试数组的所有元素是否相等:

let array = [1, 1, 1]

let hasAllItemsEqual = array.dropFirst().allSatisfy({ $0 == array.first })
print(hasAllItemsEqual) // prints: true
let array = [1, 1, 3]

let hasAllItemsEqual = array.dropFirst().allSatisfy({ $0 == array.first })
print(hasAllItemsEqual) // prints: false
let array = [Int]()

let hasAllItemsEqual = array.dropFirst().allSatisfy({ $0 == array.first })
print(hasAllItemsEqual) // prints: true

#2。使用Array的{​​{3}}方法

作为allSatisfy(_:)的替代方法,您可以使用reduce(_:_:)

let array = [1, 1, 1]

let hasAllItemsEqual = array.dropFirst().reduce(true) { (partialResult, element) in
    return partialResult && element == array.first
}
print(hasAllItemsEqual) // prints: true
let array = [1, 1, 3]

let hasAllItemsEqual = array.dropFirst().reduce(true) { (partialResult, element) in
    return partialResult && element == array.first
}
print(hasAllItemsEqual) // prints: false
let array = [Int]()

let hasAllItemsEqual = array.dropFirst().reduce(true) { (partialResult, element) in
    return partialResult && element == array.first
}
print(hasAllItemsEqual) // prints: true

#3。使用allSatisfy(_:)方法

elementsEqual(_:)返回一个布尔值,该值指示两个序列是否包含相同顺序的相同元素。因此,您可以通过重复初始数组的第一个元素并将其与后者进行比较来创建新集合:

let array = [1, 1, 1]

precondition(!array.isEmpty)
let repeated = repeatElement(array[0], count: array.count)

let hasAllItemsEqual = array.elementsEqual(repeated)
print(hasAllItemsEqual) // prints: true
let array = [1, 1, 3]

precondition(!array.isEmpty)
let repeated = repeatElement(array[0], count: array.count)

let hasAllItemsEqual = array.elementsEqual(repeated)
print(hasAllItemsEqual) // prints: false

#4。使用Set的{​​{3}}初始化器

如果数组中的所有元素都相等,则从该数组创建一个集合将导致该集合中只有一个元素:

let array = [1, 1, 1]

let set = Set(array)
let hasAllItemsEqual = set.count <= 1
print(hasAllItemsEqual) // prints: true
let array = [1, 1, 3]

let set = Set(array)
let hasAllItemsEqual = set.count <= 1
print(hasAllItemsEqual) // prints: false
let array = [Int]()

let set = Set(array)
let hasAllItemsEqual = set.count <= 1
print(hasAllItemsEqual) // prints: true