解决这个问题的一个好方法是使用 Swift Array 的扩展,或者在本例中为所有 Bi DirectionCollection 对象(包括数组)提供更通用的解决方案。
下面提供了从数组中获取指定对象之后的下一个或上一个对象的方法,如果您希望函数在数组末尾循环,则可以使用可选参数。
如果原始对象不存在于数组中,并且对于非循环函数,如果您要求第一个对象的前一项或最后一个对象后面的项,这些函数将返回 nil。
//
// Array+Iterator.swift
//
extension BidirectionalCollection where Iterator.Element: Equatable {
typealias Element = Self.Iterator.Element
func after(_ item: Element, loop: Bool = false) -> Element? {
if let itemIndex = self.index(of: item) {
let lastItem: Bool = (index(after:itemIndex) == endIndex)
if loop && lastItem {
return self.first
} else if lastItem {
return nil
} else {
return self[index(after:itemIndex)]
}
}
return nil
}
func before(_ item: Element, loop: Bool = false) -> Element? {
if let itemIndex = self.index(of: item) {
let firstItem: Bool = (itemIndex == startIndex)
if loop && firstItem {
return self.last
} else if firstItem {
return nil
} else {
return self[index(before:itemIndex)]
}
}
return nil
}
}
Usage:如果您有一系列孩子,并且想知道 Jane 之后的孩子,您可以使用以下命令:
let nextChild = children.after(jane)
如果您只是想知道轮到谁洗碗,而 Sammy 昨晚洗了碗,您可以使用:
let dishwasherTonight = children.after(sammy, loop: true)
这样,如果萨米是最小的孩子,那么当我们循环回到数组的开头时,他最大的兄弟姐妹将被分配今晚洗碗。
后记:注意代码中与 endIndex 的比较该属性的定义 https://developer.apple.com/documentation/swift/collection:
您可以通过下标访问集合的元素:
使用除集合的 endIndex 属性之外的任何有效索引。这
属性是一个“过去的”索引,不与任何
集合的元素。