在Swift中使用索引迭代集合的正确和惯用方法?

时间:2016-07-09 11:52:19

标签: swift

我想迭代任意Swift集合并获取元素及其索引。

基本上可以替代:

for (idx, el) in collection.enumerate() {
    print("element at \(idx) is \(el)")
}

但是这给了我真正的通用索引,而不仅仅是从0开始的顺序整数。

当然,该解决方案将成为接受任何类型集合的泛型函数的一部分,否则差异不会非常重要。

有没有比下面的天真循环更好的方法?

var idx = collection.startIndex, endIdx = collection.endIndex
while idx < endIdx {
    let el = collection[idx]
    print("element at \(idx) is \(el)")
    idx = idx.successor()
}

写作似乎容易出错。我知道我可以将代码转换为代码片段,但如果可能的话,我想找到更简洁,更惯用的解决方案。

1 个答案:

答案 0 :(得分:1)

对于任何集合,indices属性返回有效范围 指数。迭代索引和相应的元素 与此同时,您可以使用zip()

for (idx, el) in zip(collection.indices, collection) {
    print(idx, el)
}

数组切片的示例:

let a = ["a", "b", "c", "d", "e", "f"]
let slice = a[2 ..< 5]

for (idx, el) in zip(slice.indices, slice) {
    print("element at \(idx) is \(el)")
}

输出:

element at 2 is c
element at 3 is d
element at 4 is e

您可以为此目的定义自定义扩展方法 (取自How to enumerate a slice using the original indices?):

// Swift 2:
extension CollectionType {
    func indexEnumerate() -> AnySequence<(index: Index, element: Generator.Element)> {
        return AnySequence(zip(indices, self))
    }
}

// Swift 3:
extension Collection {
    func indexEnumerate() -> AnySequence<(Indices.Iterator.Element, Iterator.Element)> {
        return AnySequence(zip(indices, self))
    }
}

角色视图示例:

let chars = "az".characters
for (idx, el) in chars.indexEnumerate() {
    print("element at \(idx) is \(el)")
}

输出:

element at 0 is a
element at 1 is 
element at 3 is 
element at 7 is z