数组[Any]和contains()

时间:2015-12-04 05:36:42

标签: swift enumeration

我试图测试[Any]类型的数组是否包含特定类型的值(例如Int)。

我知道Swift不知道如何比较Int和任意类型的值,我想这是在自动完成模板中表达的内容:

contains(predicate: (protocol<>) throws -> Bool)

所以我尝试了这段代码:

let intValue:Int = 5 // for example

let isContained = myArrayOfAny.contains({ element in 
    return ((element as? Int) == intValue)
})

...它编译(无法确保它的工作原理);但仍然无法制作predicate: (protocol<>)部分的正面或反面。这是什么意思? SequenceType的文档非常神秘:

contains(_: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
 Default Implementation
Return true iff an element in self satisfies predicate.

Declaration
@warn_unused_result func contains(@noescape _ predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool

编辑:我很困惑,因为我所看到的所有搜索结果都使用了contains()的{​​{1}}方法进行遏制测试,例如:

Array

而不是关闭。

1 个答案:

答案 0 :(得分:8)

有两种不同的contains()方法(两种协议 SequenceType的扩展名。第一个是

extension SequenceType where Generator.Element : Equatable {
    /// Return `true` iff `element` is in `self`.
    @warn_unused_result
    public func contains(element: Self.Generator.Element) -> Bool
}

并且它要求序列元素符合Equatable 协议,保证可以将它们与==进行比较:

public protocol Equatable {
    // ...
    public func ==(lhs: Self, rhs: Self) -> Bool
}

例如,在

let intValue:Int = 5
let myArrayOfInt = [4, 5, 6]
let isContained = myArrayOfInt.contains(intValue)

您有一个Int数组,Int符合Equatable, 所以这个contains()方法可用于检查是否存在 某个元素。

这不适用于

let myArrayOfAny : [Any] = [4, 5, 6]

因为Any不符合Equatable。在这里你可以使用 第二个contains()方法

extension SequenceType {
    /// Return `true` iff an element in `self` satisfies `predicate`.
    @warn_unused_result
    public func contains(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
}

采用谓词,即布尔函数。代替 与==比较,谓词应用于每个数组元素。 此方法不要求数组元素为Equatable

这就是你在

中所做的
let myArrayOfAny : [Any] = [4, 5, 6]
let intValue:Int = 5 // for example
let isContained = myArrayOfAny.contains({ element in 
    return ((element as? Int) == intValue)
})

如果可以将任何数组元素强制转换为true,则会产生Int 并且等于给定的intValue

可能会更频繁地看到第一种方法,但第二种方法 更为通用,例如。

if myArrayOfCustomObjects.contains ({ $0.someProperty == "foo" })

if myArrayOfInts.contains ({ $0 > 17 })

所以第一个contains()是第二个的专门化,用于在equatable元素的数组中进行简单的包含检查。它可以实现为

extension SequenceType where Generator.Element : Equatable {

    public func contains(element: Self.Generator.Element) -> Bool {
        return self.contains({ $0 == element } )
    }
}

你会发现indexOf()也是如此 两种口味:

extension CollectionType where Generator.Element : Equatable {
    // ...
    public func indexOf(element: Self.Generator.Element) -> Self.Index?
}

extension CollectionType {
    // ...
    public func indexOf(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Index?
}