随机阵列swift 3

kye*_*kye 29 swift swift3

如何将以下功能转换为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])
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*n R 78

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

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

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])
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,根据新的"Swift API设计指南", shuffle()是变异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
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:一个(甚至更一般)Swift 3版本已被添加到 如何在Swift中混洗数组?同时.


对于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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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


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

  • 你是个天才 (3认同)

Jos*_*ann 10

Gamekit中有一个渔民洗牌:

import GameKit
let unshuffledArray = [1,2,3,4]
let shuffledArray = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: unshuffledArray)
print(shuffledArray)
Run Code Online (Sandbox Code Playgroud)

您还可以传入并存储随机种子,因此每次提供相同的种子时都会获得相同的伪随机混响值序列,以防您需要重新创建模拟.

import GameKit
let unshuffledArray = [1,2,3,4]
let randomSource = GKLinearCongruentialRandomSource(seed: 1)
let shuffledArray = randomSource.arrayByShufflingObjects(in: unshuffledArray)
//Always [1,4,2,3]
print(shuffledArray)
Run Code Online (Sandbox Code Playgroud)


mat*_*att 8

我建议简单地改组数组,而不是试图将它扩展到集合中:

extension Array {
    mutating func shuffle () {
        for i in (0..<self.count).reversed() {
            let ix1 = i
            let ix2 = Int(arc4random_uniform(UInt32(i+1)))
            (self[ix1], self[ix2]) = (self[ix2], self[ix1])
        }
    }
}
Run Code Online (Sandbox Code Playgroud)