一尘不染

随机排列swift 3

swift

如何将下面的函数转换为swift 3?当前出现Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance'错误。

extension MutableCollection where Index == Int {
  /// Shuffle the elements of `self` in-place.
  mutating func shuffleInPlace() {
    // empty and single-element collections don't shuffle
    if count < 2 { return }

    for i in 0..<count - 1 { //error takes place here
      let j = Int(arc4random_uniform(UInt32(count - i))) + i
      guard i != j else { continue }
      swap(&self[i], &self[j])
    }
  }
}

阅读 271

收藏
2020-07-07

共1个答案

一尘不染

count返回,IndexDistance它是描述两个集合索引之间距离的类型。IndexDistance必须为SignedInteger,但不必为Int,可以与有所不同Index。因此,不可能创建范围0..<count - 1

一个解决方案是使用startIndexendIndex代替0and count

extension MutableCollection where Index == Int {
    /// Shuffle the elements of `self` in-place.
    mutating func shuffle() {
        // empty and single-element collections don't shuffle
        if count < 2 { return }

        for i in startIndex ..< endIndex - 1 {
            let j = Int(arc4random_uniform(UInt32(endIndex - i))) + i
            if i != j {
                swap(&self[i], &self[j])
            }
        }
    }
}

另一个优点是,它也可以与数组 切片 正确配合使用 (第一个元素的索引不一定为零)。

请注意,根据新的“ Swift API设计指南”,它 shuffle()是变异随机播放方法和shuffled()返回数组的非变异对应方法的“适当”名称:

extension Collection {
    /// Return a copy of `self` with its elements shuffled
    func shuffled() -> [Iterator.Element] {
        var list = Array(self)
        list.shuffle()
        return list
    }
}

_更新:_我已经在Swift中添加了一个(甚至更通用的)Swift 3版本


对于 Swift 4(Xcode 9) ,必须用对集合方法的swap()
调用来代替对函数的调用swapAt()。同样,Index不再需要对类型的限制:

extension MutableCollection {
    /// Shuffle the elements of `self` in-place.
    mutating func shuffle() {
        for i in indices.dropLast() {
            let diff = distance(from: i, to: endIndex)
            let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
            swapAt(i, j)
        }
    }
}

有关的更多信息,请参见SE-0173MutableCollection.swapAt(_:_:)swapAt


Swift 4.2 (Xcode 10,当前处于beta版)开始,具有 SE-0202 Random
Unification的实现

shuffle()并且shuffled()是Swift标准库的一部分。

2020-07-07