Swift3/Swift4实现Fisher–Yates洗牌算法随机打乱数组(shuffle)

添加两个extension:

  • 可变集合添加shuffle()方法,打乱原来集合的元素顺序
  • Sequence添加shuffled()方法,返回原序列乱序的数组

Swift 4

extension MutableCollection {
    /// 打乱集合里的元素
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            let i = index(firstUnshuffled, offsetBy: d)
            swapAt(firstUnshuffled, i)
        }
    }
}

extension Sequence {
    /// 返回序列乱序的数组
    func shuffled() -> [Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

Swift 3

extension MutableCollection where Indices.Iterator.Element == Index {
    /// 打乱集合里的元素
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            guard d != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            swap(&self[firstUnshuffled], &self[i])
        }
    }
}

extension Sequence {
    /// 返回序列乱序的数组
    func shuffled() -> [Iterator.Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

使用

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 3/4缩放UIImage的方法

给UIImage添加extension(兼容Swift3 和Swift 4)extension UIImage {     func scaled(withSize size: CGSize) -> UIImage {   &nbs

Swift 4:KeyPath

Swift 4对KeyPath做了很大的改进。改进后的为类型安全的KeyPath。Swift 2的KeyPath示例class Person: NSObject {   var name: String = ""   init(name: 

Swift日期和字符串互相转换(Swift 3/Swift 4)

Swift随着版本的升级,日期类都会有一点变化。所以各个版本的Swift日期和字符串的转换有所不同。Swift 4String转换为Datevar dateString = "2017-11-17" var dateFormatter = DateFormatter() // dateFormat

使用Swift 3/Swift 4扫描二维码

iOS的AVFoundation内置了对二维码和条形码扫描的支持。使用AVFoundation扫描二维码的功能需要几件事:创建AVCaptureSession,用于捕获二维码创建预览捕获二维码成功后,委派回调来处理二维码的meta信息下面的例子是基于UIViewController开发的扫描二维码Controller,使用AVCaptureMetadataOutputObjectsDelegate

Swift3/Swift4 转换Html为纯文本

Swift 3或者Swift 4 添加String扩展,把Html字符串转换为纯文本Xcode 9 beta • Swift 4extension String {     var html2AttributedString: NSAttr

禁用Xcode 9的Swift 3 @objc推断

今天我安装了Xcode 9,并将我的项目转换为Swift 4.0。 令人惊讶的是,我的代码只需做很少的改动就可以兼容新的Swift。 然而,构建后出现一个警告:The use of Swift 3 @objc inference in Swift 4 mode