我正在研究 Collection 协议并决定实现自己的集合,但我并没有就此止步,而是想实现 index(after:) 方法,以便它以相反的方式工作
struct SimpleCollection: Collection {
var numbers = [1, 2, 3, 4, 5]
var startIndex: Int { numbers.startIndex }
var endIndex: Int { numbers.endIndex }
subscript(index: Int) -> Int {
return numbers[index]
}
func index(after i: Int) -> Int {
return numbers.index(after: i)
}
}
这是我的结构,我想实现 Index(after:) 方法,以便它以相反的方向输出
let test = SimpleCollection();
for items in test{
print(items)
}
现在显示什么
1
2
3
4
5
我想要什么
5
4
3
2
1
为此,您不仅必须正确实现
index(after:)
,还必须正确实现 startIndex
、endIndex
和下标。您当前的实现不会创建反向集合 - test[test.startIndex]
应该返回 5,但它返回 1。
一个简单的想法是让集合的
startIndex
成为数组的 endIndex
,这同样适用于 endIndex
。
var startIndex: Int { numbers.endIndex }
var endIndex: Int { numbers.startIndex }
现在我们遇到了另一个问题。
test[numbers.startIndex]
崩溃,因为 numbers.endIndex
不是 numbers
的有效索引。我们需要改变下标的实现来使用之前的索引。
subscript(index: Int) -> Int {
return numbers[numbers.index(before: index)] // or just numbers[index - 1]
}
最后,我们实现了
index(after:)
,这很简单。只需返回给定索引之前的索引即可。
func index(after i: Int) -> Int {
return numbers.index(before: i) // or just i - 1
}
ReversedCollection
(由 reversed
方法返回的类型)。查看其实现,了解如何在一般情况下执行此操作,其中底层集合可以是任何BidirectionalCollection
。
主要思想与我上面展示的相同,但值得注意的是,内置
ReversedCollection
使用自定义 Index
类型,而不是使用与底层集合相同的 Index
。这清楚地区分了反向集合的索引与原始集合的索引,它们在语义上非常不同。