【问题标题】:Swift negative indexing in arrays数组中的 Swift 负索引
【发布时间】:2015-09-09 21:42:31
【问题描述】:

是否可以覆盖 Swift 的默认数组下标,以便它像 Python 一样处理负索引?

例如,a[-1] 应该返回 a 的最后一个元素,a[-2] 应该返回它之前的元素。

这应该可以通过扩展Array类型来实现,唉,下面的代码将无法工作,因为它会无限循环:

extension Array {
   subscript (index:Int) -> [Element] {
        return (index < 0) ? self[self.count+index] : self[index]
   }
}

重写一些基本的东西的想法有多糟糕?

【问题讨论】:

  • 就我个人而言,我认为这是一个非常糟糕的主意。这很容易让毫无戒心的开发人员重用/维护您的代码。
  • 最简单的公式其实是:unsignedIndex = signedIndex % arrayCount。即return self[signedIndex % count]。但是这样索引永远不会溢出,所以要小心。

标签: arrays swift foundation


【解决方案1】:

Swift 4 版本:

extension Collection where Index: Comparable {
    subscript(back i: Int) -> Iterator.Element {
        let backBy = i + 1
        return self[self.index(self.endIndex, offsetBy: -backBy)]
    }
}

【讨论】:

  • 这有一些问题,所以我已经纠正了它们。它实际上并不依赖 IndexComparable 所以我删除了约束。它现在扩展了BidirectionalCollection,保证我们可以向后迭代。并且没有必要将偏移量增加 1;这导致我们走得太远(-1 应该是最后一个元素,而不是倒数第二个)。
【解决方案2】:

实际上,有一个相对良好的实践,快速的方式来做到这一点:标记参数。

extension CollectionType where Index : BidirectionalIndexType {
  subscript(back i: Index.Distance) -> Generator.Element {
    return self[endIndex.advancedBy(-i)]
  }
}

let ar = [1, 2, 3, 4]
ar[back: 1] // 4
ar[back: 2] // 3

你显然可以很容易地改变语义。例如,此实现要求索引大于 0。将其更改为 0 返回最后一个元素就像:self[endIndex.predecessor().advancedBy(-i)],或者,如果您想假设索引为负,请输入:self[endIndex.advancedBy(-i)]

labeled 参数的优点是它很清楚,没有人会意外使用它。

【讨论】:

    猜你喜欢
    • 2020-02-03
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 2013-04-01
    • 1970-01-01
    • 2017-03-13
    • 2013-03-21
    相关资源
    最近更新 更多