实现index(after:)方法倒序显示

问题描述 投票:0回答:1

我正在研究 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
swift swift-protocols
1个回答
0
投票

为此,您不仅必须正确实现

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
。这清楚地区分了反向集合的索引与原始集合的索引,它们在语义上非常不同。

© www.soinside.com 2019 - 2024. All rights reserved.