Dun*_*age 11
解决这个问题的一个好方法是使用Swift数组的扩展,或者在这种情况下,为所有BidirectionalCollection对象(包括数组)提供更通用的解决方案.
下面提供了从数组中获取指定对象之后的下一个或上一个对象的方法,如果希望函数在数组的末尾循环,则使用可选参数.
对于非循环函数,如果原始对象不存在于数组中,并且如果要求前一项到第一个对象或最后一个对象后面的项,则这些函数返回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
}
}
Run Code Online (Sandbox Code Playgroud)
用法: 如果您有一系列孩子,并想知道Jane之后的孩子,您将使用以下内容:
let nextChild = children.after(jane)
Run Code Online (Sandbox Code Playgroud)
如果你只是想知道轮到你做什么菜,而Sammy昨晚做了,你会改用:
let dishwasherTonight = children.after(sammy, loop: true)
Run Code Online (Sandbox Code Playgroud)
这样,如果Sammy是最小的孩子,他们最老的兄弟姐妹今晚会被分配来洗碗,因为我们会回到阵列的开头.
后记:注意在代码中将endIndex 与该属性的定义进行比较:
您可以使用除集合的endIndex属性之外的任何有效索引通过其下标访问集合的元素.此属性是"过去结束"索引,与集合的任何元素都不对应.
Ale*_*ica 10
我提出了一个更简单,更彻底的实现:
extension Collection where Iterator.Element: Equatable {
typealias Element = Self.Iterator.Element
func safeIndex(after index: Index) -> Index? {
let nextIndex = self.index(after: index)
return (nextIndex < self.endIndex) ? nextIndex : nil
}
func index(afterWithWrapAround index: Index) -> Index {
return self.safeIndex(after: index) ?? self.startIndex
}
func item(after item: Element) -> Element? {
return self.index(of: item)
.flatMap(self.safeIndex(after:))
.map{ self[$0] }
}
func item(afterWithWrapAround item: Element) -> Element? {
return self.index(of: item)
.map(self.index(afterWithWrapAround:))
.map{ self[$0] }
}
}
extension BidirectionalCollection where Iterator.Element: Equatable {
typealias Element = Self.Iterator.Element
func safeIndex(before index: Index) -> Index? {
let previousIndex = self.index(before: index)
return (self.startIndex <= previousIndex) ? previousIndex : nil
}
func index(beforeWithWrapAround index: Index) -> Index {
return self.safeIndex(before: index) ?? self.index(before: self.endIndex)
}
func item(before item: Element) -> Element? {
return self.index(of: item)
.flatMap(self.safeIndex(before:))
.map{ self[$0] }
}
func item(beforeWithWrapAround item: Element) -> Element? {
return self.index(of: item)
.map(self.index(beforeWithWrapAround:))
.map{ self[$0] }
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3624 次 |
| 最近记录: |