【问题标题】:A correct and idiomatic way to iterate through a collection with index in Swift?在 Swift 中使用索引遍历集合的正确且惯用的方法?
【发布时间】:2016-07-09 11:52:18
【问题描述】:

我想遍历任意 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()
}

这样的写作似乎很容易出错。我知道我可以将该代码转换为 sn-p,但如果可能的话,我想找到一个更简洁、更惯用的解决方案。

【问题讨论】:

  • 从我的测试中 idx.dynamicType 是 Int 但你说通用索引我错过了什么吗?
  • @AliKıran:这取决于收藏。数组具有整数索引,但例如字符串具有特殊的 String.CharacterView.Index 类型。集合的索引也不必从零开始(例如数组切片)。
  • 我希望链接到的“重复”可以解决您的问题。否则请告诉我,我会重新提出问题。
  • @MartinR 谢谢我明白了我只是误解了这个问题
  • @MartinR 谢谢,另一个问题的表述更为狭隘,但答案完全正确。不过,我认为这个问题的答案更好,更中肯。我不确定这种情况下的 SO 政策是什么;如果由我自行决定,我会留下两者。谢谢!

标签: swift


【解决方案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)")
}

输出:

2 处的元素是 c 3 处的元素是 d 4 处的元素是 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 = "a???z".characters
for (idx, el) in chars.indexEnumerate() {
    print("element at \(idx) is \(el)")
}

输出:

0 处的元素是 1 处的元素是? 3 的元素是?? 7 处的元素是 z

【讨论】:

  • 为什么chars 示例的索引是 0、1、3、7 而不是 0、1、2、3?
  • @dantiston:因为字符串索引在内部引用 UTF-16 代码点。但你不应该关心这些数字。如果您使用正确的方法(如 advancedBy、distanceTo)对索引进行操作,一切都会按预期进行。
猜你喜欢
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-11
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
相关资源
最近更新 更多