如何在Swift中对数组进行混洗?

本文翻译自:How do I shuffle an array in Swift?

How do I randomize or shuffle the elements within an array in Swift? 如何在Swift中随机或随机排列数组中的元素? For example, if my array consists of 52 playing cards, I want to shuffle the array in order to shuffle the deck. 例如,如果我的阵列由52张扑克牌,我想洗牌的阵列,以洗牌。


#1楼

参考:https://stackoom.com/question/1coOM/如何在Swift中对数组进行混洗


#2楼

Here's some code that runs in playground. 这是在操场上运行的一些代码。 You won't need to import Darwin in an actual Xcode project. 您无需在实际的Xcode项目中导入Darwin。

import darwin

var a = [1,2,3,4,5,6,7]

func shuffle<ItemType>(item1: ItemType, item2: ItemType) -> Bool {
    return drand48() > 0.5
}

sort(a, shuffle)

println(a)

#3楼

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. 该答案详细说明了如何在Swift 4.2+中使用快速统一的算法(Fisher-Yates)进行改组,以及如何在各个早期版本的Swift中添加相同的功能。 The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version. 每个Swift版本的命名和行为都与该版本的变异和非变异排序方法匹配。

Swift 4.2+ 迅捷4.2+

shuffle and shuffled are native starting Swift 4.2. shuffleshuffled是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 and 4.1 Swift 4.0和4.1

These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence: 这些扩展将shuffle()方法添加到任何可变集合(数组和不安全的可变缓冲区),并将shuffled()方法添加到任何序列:

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

Same usage as in Swift 4.2 examples above. 与上述Swift 4.2示例中的用法相同。


Swift 3 迅捷3

These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence: 这些扩展将shuffle()方法添加到任何可变集合中,并将shuffled()方法添加到任何序列中:

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

Same usage as in Swift 4.2 examples above. 与上述Swift 4.2示例中的用法相同。


Swift 2 迅捷2

(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018) (过时的语言:自2018年7月起,您将无法使用Swift 2.x在iTunes Connect上发布)

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

Usage: 用法:

[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]

Swift 1.2 斯威夫特1.2

(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018) (过时的语言:自2018年7月起,您将无法使用Swift 1.x在iTunes Connect上发布)

shuffle as a mutating array method shuffle为变异数组方法

This extension will let you shuffle a mutable Array instance in place: 通过此扩展,您可以在适当位置随机播放可变的Array实例:

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 as a non-mutating array method shuffled为非变异数组方法

This extension will let you retrieve a shuffled copy of an Array instance: 通过此扩展,您可以检索Array实例的随机组合副本:

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]

#4楼

这可能更短一些:

sorted(a) {_, _ in arc4random() % 2 == 0}

#5楼

You can use generic swap function as well and implement mentioned Fisher-Yates: 您还可以使用通用swap函数并实现提到的Fisher-Yates:

for idx in 0..<arr.count {
  let rnd = Int(arc4random_uniform(UInt32(idx)))
  if rnd != idx {
    swap(&arr[idx], &arr[rnd])
  }
}

or less verbose: 或更详细:

for idx in 0..<steps.count {
  swap(&steps[idx], &steps[Int(arc4random_uniform(UInt32(idx)))])
}

#6楼

This is what I use: 这是我用的:

func newShuffledArray(array:NSArray) -> NSArray {
    var mutableArray = array.mutableCopy() as! NSMutableArray
    var count = mutableArray.count
    if count>1 {
        for var i=count-1;i>0;--i{
            mutableArray.exchangeObjectAtIndex(i, withObjectAtIndex: Int(arc4random_uniform(UInt32(i+1))))
        }
    }
    return mutableArray as NSArray
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值