随机排列数组 swift 3 [英] Shuffle array swift 3

查看:15
本文介绍了随机排列数组 swift 3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将下面的函数转换为 swift 3?当前获得 二元运算符 '..<'不能应用于类型为Int"和Self.IndexDistance"的操作数错误.

How can I convert the function below to to swift 3? Currently getting a Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance' error.

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])
    }
  }
}

参考:https://stackoverflow.com/a/24029847/5222077

推荐答案

count 返回一个 IndexDistance 这是描述的类型两个集合索引之间的距离.IndexDistance 是必须是 SignedInteger,但不必是 Int 并且可以不同于Index.因此无法创建范围 0...

count returns an IndexDistance which is the type describing the distance between two collection indices. IndexDistance is required to be a SignedInteger, but need not be an Int and can be different from Index. Therefore it is not possible to create the range 0..<count - 1.

一个解决方案是使用 startIndexendIndex 而不是 0count:

A solution is to use startIndex and endIndex instead of 0 and 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])
            }
        }
    }
}

另一个优点是这也适用于数组 slices(其中第一个元素的索引不一定为零).

Another advantage is that this also works correctly with array slices (where the index of the first element is not necessarily zero).

请注意,根据新的 Swift API 设计指南"shuffle() 是变异 shuffle 方法的正确"名称,和 shuffled() 用于返回数组的非变异对应物:

Note that according to the new "Swift API Design Guidelines", shuffle() is the "proper" name for a mutating shuffle method, and shuffled() for the non-mutating counterpart which returns an array:

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

更新:一个(更通用的)Swift 3 版本已添加到如何在 Swift 中随机排列数组? 同时.

Update: A (even more general) Swift 3 version has been added to How do I shuffle an array in Swift? in the meantime.

对于 Swift 4 (Xcode 9) 必须替换对 swap() 的调用通过调用集合的 swapAt() 方法来实现.也不再需要对 Index 类型的限制:

For Swift 4 (Xcode 9) one has to replace the call to the swap() function by a call to the swapAt() method of the collection. Also the restriction on the Index type is no longer needed:

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-0173 添加 MutableCollection.swapAt(_:_:) 有关 swapAt 的更多信息.

Swift 4.2(Xcode 10,目前处于测试阶段)开始,实现了SE-0202 随机统一shuffle()shuffled() 是 Swift 标准库的一部分.

As of Swift 4.2 (Xcode 10, currently in beta), with the implementation of SE-0202 Random Unification, shuffle() and shuffled() are part of the Swift standard library.

这篇关于随机排列数组 swift 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆