如何在Swift中对数组进行混洗? [英] How do I shuffle an array in Swift?

查看:109
本文介绍了如何在Swift中对数组进行混洗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Swift中随机或随机排列数组中的元素?例如,如果我的阵列包含52张扑克牌,我想 shuffle (阵列)以随机洗牌.

How do I randomize or shuffle the elements within an array in Swift? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck.

推荐答案

此答案详细介绍了如何在Swift 4.2+中使用快速且统一的算法(Fisher-Yates)进行改编,以及如何在以前的各个版本中添加相同功能斯威夫特.每个Swift版本的命名和行为都与该版本的变异和非变异排序方法相匹配.

This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.

shuffle

shuffle and shuffled are native starting Swift 4.2. Example usage:

let x = [1, 2, 3].shuffled()
// x == [2, 3, 1]

let fiveStrings = stride(from: 0, through: 100, by: 5).map(String.init).shuffled()
// fiveStrings == ["20", "45", "70", "30", ...]

var numbers = [1, 2, 3, 4]
numbers.shuffle()
// numbers == [3, 2, 1, 4]

Swift 4.0和4.1

这些扩展将shuffle()方法添加到任何可变集合(数组和不安全的可变缓冲区),并且将shuffled()方法添加到任何序列:

Swift 4.0 and 4.1

These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:

extension MutableCollection {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            // Change `Int` in the next line to `IndexDistance` in < Swift 4.1
            let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            let i = index(firstUnshuffled, offsetBy: d)
            swapAt(firstUnshuffled, i)
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

用法与上面的Swift 4.2示例相同.

Same usage as in Swift 4.2 examples above.

这些扩展将shuffle()方法添加到任何可变集合中,并且将shuffled()方法添加到任何序列中:

These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:

extension MutableCollection where Indices.Iterator.Element == Index {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            // Change `Int` in the next line to `IndexDistance` in < Swift 3.2
            let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            guard d != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            self.swapAt(firstUnshuffled, i)
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Iterator.Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

用法与上面的Swift 4.2示例相同.

Same usage as in Swift 4.2 examples above.

(过时的语言:您不能使用Swift 2.x从2018年7月开始在iTunes Connect上发布)

(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)

extension MutableCollectionType 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 startIndex ..< endIndex - 1 {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            guard i != j else { continue }
            swap(&self[i], &self[j])
        }
    }
}

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

用法:

[1, 2, 3].shuffle()
// [2, 3, 1]

let fiveStrings = 0.stride(through: 100, by: 5).map(String.init).shuffle()
// ["20", "45", "70", "30", ...]

var numbers = [1, 2, 3, 4]
numbers.shuffleInPlace()
// [3, 2, 1, 4]


雨燕1.2

(过时的语言:您不能使用Swift 1.x从2018年7月开始在iTunes Connect上发布)


Swift 1.2

(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)

此扩展程序可让您在适当的位置随机播放一个可变的Array实例:

This extension will let you shuffle a mutable Array instance in place:

extension Array {
    mutating func shuffle() {
        if count < 2 { return }
        for i in 0..<(count - 1) {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            swap(&self[i], &self[j])
        }
    }
}
var numbers = [1, 2, 3, 4, 5, 6, 7, 8]
numbers.shuffle()                     // e.g., numbers == [6, 1, 8, 3, 2, 4, 7, 5]

shuffled作为非变异数组方法

此扩展名将使您可以检索Array实例的随机组合副本:

shuffled as a non-mutating array method

This extension will let you retrieve a shuffled copy of an Array instance:

extension Array {
    func shuffled() -> [T] {
        if count < 2 { return self }
        var list = self
        for i in 0..<(list.count - 1) {
            let j = Int(arc4random_uniform(UInt32(list.count - i))) + i
            swap(&list[i], &list[j])
        }
        return list
    }
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let mixedup = numbers.shuffled()     // e.g., mixedup == [6, 1, 8, 3, 2, 4, 7, 5]

这篇关于如何在Swift中对数组进行混洗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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