这里有个名为 findIndex(ofString:in:)
的非泛型函数,该函数的功能是在一个 String
数组中查找给定 String
值的索引。若查找到匹配的字符串,findIndex(ofString:in:)
函数返回该字符串在数组中的索引值,否则返回nil:
func findIndex(ofString valueToFind: String, in array: [String]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
findIndex(ofString:in:)
函数可以用于查找字符串数组中的某个字符串值:
let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
if let foundIndex = findIndex(ofString: "llama", in: strings) {
print("The index of llama is \(foundIndex)")
}
// 打印“The index of llama is 2”
如果只能查找字符串在数组中的索引,用处不是很大。不过,你可以用占位类型 T 替换 String 类型来写出具有相同功能的泛型函数 findIndex(_:_:)
下面展示了findIndex(ofString:in:)
函数的泛型版本 findIndex(of:in:)
。请注意这个函数返回值的类型仍然是Int?
,这是因为函数返回的是一个可选的索引数,而不是从数组中得到的一个可选值。需要提醒的是,这个函数无法通过编译,原因将在后面说明:
func findIndex<T>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
上面所写的函数无法通过编译。问题出在相等性检查上,即"if value == valueToFind"
。不是所有的 Swift 类型都可以用等式符(==)
进行比较。例如,如果你自定义类或结构体来描述复杂的数据模型,对于这个类或结构体而言,Swift 无法明确知道“相等”意味着什么。正因如此,这部分代码无法保证适用于任意类型T
,当你试图编译这部分代码时就会出现相应的错误。
不过,所有的这些并不会让我们无从下手。Swift 标准库中定义了一个 Equatable
协议,该协议要求任何遵循该协议的类型必须实现等式符(==)
及不等符(!=)
,从而能对该类型的任意两个值进行比较。所有的 Swift 标准类型自动支持Equatable
协议。
遵循 Equatable
协议的类型都可以安全地用于findIndex(of:in:)
函数,因为其保证支持等式操作符。为了说明这个事情,当定义一个函数时,你可以定义一个 Equatable
类型约束作为类型参数定义的一部分:
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
findIndex(of:in:)
类型参数写做 T: Equatable
,也就意味着“任何符合 Equatable
协议的类型 T
”。
findIndex(of:in:)
函数现在可以成功编译了,并且适用于任何符合Equatable
的类型,如 Double
或 String
:
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
// doubleIndex 类型为 Int?,其值为 nil,因为 9.3 不在数组中
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
// stringIndex 类型为 Int?,其值为 2
网友评论