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

How do I shuffle an array in Swift?

如何快速随机化或洗牌数组中的元素?例如,如果我的阵列由52张扑克牌组成,我想洗牌以洗牌。


这个答案详细说明了如何在Swift 4.2+中使用快速统一的算法(Fisher Yates),以及如何在之前的各种版本的Swift中添加相同的功能。每个swift版本的命名和行为与该版本的突变和非突变排序方法相匹配。

斯威夫特4.2 +

shuffleshuffled是本地启动的swift 4.2。示例用法:

1
2
3
4
5
6
7
8
9
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()方法添加到任何序列中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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示例中的用法相同。

斯威夫特3

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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示例中的用法相同。

斯威夫特2

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
4
5
6
7
8
9
[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

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

shuffle作为一种可变数组方法

此扩展将允许您在适当的位置移动可变的Array实例:

1
2
3
4
5
6
7
8
9
10
11
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实例的无序副本:

1
2
3
4
5
6
7
8
9
10
11
12
13
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]


编辑:如其他答案所述,Swift4.2最终将随机数生成添加到标准库中,并完成数组洗牌。

但是,gameplaykit中的GKRandom/GKRandomDistribution套件在新的RandomNumberGenerator协议中仍然有用-如果您向gameplaykit rngs添加扩展以符合新的标准库协议,您可以很容易地获得:

  • 可发送的RNG(当测试需要时,可以复制"随机"序列)
  • 为速度牺牲鲁棒性的RNG
  • 产生非均匀分布的RNG

…并且仍然可以在swift中使用新的"本地"随机API。

其余的答案与这些RNG和/或它们在旧的swift编译器中的使用有关。

这里已经有一些很好的答案,以及一些很好的说明,如果你不小心的话,为什么写你自己的洗牌会容易出错。

在iOS 9、MacOS 10.11和TVOS 9(或更高版本)中,您不必自己编写。在Gameplaykit中有一个高效、正确的Fisher Yates的实现(尽管它的名字不只是用于游戏)。

如果你只想要一个独特的洗牌:

1
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)

如果您希望能够复制一个随机播放或一系列随机播放,请选择一个特定的随机播放源并为其种子;例如。

1
2
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)

在iOS 10/MacOS 10.12/TVOS 10中,还有一种方便的语法,可以通过EDOCX1上的扩展(17)进行洗牌。当然,当您使用Swift Array时,这有点麻烦(当返回Swift时,它会丢失其元素类型):

1
2
let shuffled1 = (array as NSArray).shuffled(using: random) // -> [Any]
let shuffled2 = (array as NSArray).shuffled() // use default random source

但是很容易制作一个保存类型的Swift包装器:

1
2
3
4
5
6
7
8
9
10
extension Array {
    func shuffled(using source: GKRandomSource) -> [Element] {
        return (self as NSArray).shuffled(using: source) as! [Element]
    }
    func shuffled() -> [Element] {
        return (self as NSArray).shuffled() as! [Element]
    }
}
let shuffled3 = array.shuffled(using: random)
let shuffled4 = array.shuffled()


在Swift 2.0中,游戏工具包可能会被拯救!(由IOS9或更高版本支持)

1
2
3
4
5
import GameplayKit

func shuffle() {
    array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
}


这里有一些可能短一点的东西:

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


拿奈特的算法来说,我想看看Swift2和协议扩展的情况。

这就是我想到的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
extension MutableCollectionType where Self.Index == Int {
    mutating func shuffleInPlace() {
        let c = self.count
        for i in 0..<(c - 1) {
            let j = Int(arc4random_uniform(UInt32(c - i))) + i
            swap(&self[i], &self[j])
        }
    }
}

extension MutableCollectionType where Self.Index == Int {
    func shuffle() -> Self {
        var r = self
        let c = self.count
        for i in 0..<(c - 1) {
            let j = Int(arc4random_uniform(UInt32(c - i))) + i
            swap(&r[i], &r[j])
        }
        return r
    }
}

现在,任何MutableCollectionType都可以使用这些方法,因为它使用Int作为Index使用。


在我的例子中,我在交换数组中的对象时遇到了一些问题。然后我挠了挠头,开始重新发明轮子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// swift 3.0 ready
extension Array {

    func shuffled() -> [Element] {
        var results = [Element]()
        var indexes = (0 ..< count).map { $0 }
        while indexes.count > 0 {
            let indexOfIndexes = Int(arc4random_uniform(UInt32(indexes.count)))
            let index = indexes[indexOfIndexes]
            results.append(self[index])
            indexes.remove(at: indexOfIndexes)
        }
        return results
    }

}

这是Nate为Swift 4实施Fisher Yates Shuffle的版本(XCODER 9)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)
        }
    }
}

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

变化包括:

  • 约束条件Indices.Iterator.Element == Index现在已成为一部分。不需要强制执行扩展了。
  • 交换元素必须通过调用集合上的swapAt()来完成,比较SE-0173加MutableCollection.swapAt(_:_:)
  • ElementIterator.Element的别名。

这是我使用的:

1
2
3
4
5
6
7
8
9
10
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
}

斯威夫特4在for循环中无序排列数组元素,其中i是混合比

1
2
3
4
5
6
7
8
var cards = [Int]() //Some Array
let i = 4 // is the mixing ratio
func shuffleCards() {
    for _ in 0 ..< cards.count * i {
        let card = cards.remove(at: Int(arc4random_uniform(UInt32(cards.count))))
        cards.insert(card, at: Int(arc4random_uniform(UInt32(cards.count))))
    }
}

或扩展名为int

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func shuffleCards() {
    for _ in 0 ..< cards.count * i {
        let card = cards.remove(at: cards.count.arc4random)
        cards.insert(card, at: cards.count.arc4random)
    }
}
extension Int {
    var arc4random: Int {
        if self > 0 {
            print("Arc for random positiv self \(Int(arc4random_uniform(UInt32(self))))")
        return Int(arc4random_uniform(UInt32(self)))
        } else if self < 0 {
            print("Arc for random negotiv self \(-Int(arc4random_uniform(UInt32(abs(self)))))")
            return -Int(arc4random_uniform(UInt32(abs(self))))
        } else {
            print("Arc for random equal 0")
            return 0
        }
    }
}


有了Swift 3,如果你想将一个数组移动到位或从一个数组中获得一个新的被移动的数组,AnyIterator可以帮助你。其思想是从数组中创建一个索引数组,用AnyIterator实例和swap(_:_:)函数对这些索引进行无序处理,并将该AnyIterator实例的每个元素映射到数组的相应元素。

以下操场代码显示了它的工作原理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Darwin // required for arc4random_uniform

let array = ["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]
var indexArray = Array(array.indices)
var index = indexArray.endIndex

let indexIterator: AnyIterator<Int> = AnyIterator {
    guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
        else { return nil }

    index = nextIndex
    let randomIndex = Int(arc4random_uniform(UInt32(index)))
    if randomIndex != index {
        swap(&indexArray[randomIndex], &indexArray[index])
    }

    return indexArray[index]
}

let newArray = indexIterator.map { array[$0] }
print(newArray) // may print: ["Jock","Ellie","Sue Ellen","JR","Pamela","Bobby"]

您可以重构以前的代码,并在Array扩展内创建shuffled()函数,以便从数组中获取新的无序排列数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Darwin // required for arc4random_uniform

extension Array {

    func shuffled() -> Array<Element> {
        var indexArray = Array<Int>(indices)        
        var index = indexArray.endIndex

        let indexIterator = AnyIterator<Int> {
            guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
                else { return nil }

            index = nextIndex                
            let randomIndex = Int(arc4random_uniform(UInt32(index)))
            if randomIndex != index {
                swap(&indexArray[randomIndex], &indexArray[index])
            }

            return indexArray[index]
        }

        return indexIterator.map { self[$0] }
    }

}

用途:

1
2
3
let array = ["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]
let newArray = array.shuffled()
print(newArray) // may print: ["Bobby","Pamela","Jock","Ellie","JR","Sue Ellen"]
1
2
3
let emptyArray = [String]()
let newEmptyArray = emptyArray.shuffled()
print(newEmptyArray) // prints: []

作为前面代码的替代,您可以在Array扩展内创建一个shuffle()函数,以便在适当位置移动数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Darwin // required for arc4random_uniform

extension Array {

    mutating func shuffle() {
        var indexArray = Array<Int>(indices)
        var index = indexArray.endIndex

        let indexIterator = AnyIterator<Int> {
            guard let nextIndex = indexArray.index(index, offsetBy: -1, limitedBy: indexArray.startIndex)
                else { return nil }

            index = nextIndex                
            let randomIndex = Int(arc4random_uniform(UInt32(index)))
            if randomIndex != index {
                swap(&indexArray[randomIndex], &indexArray[index])
            }

            return indexArray[index]
        }

        self = indexIterator.map { self[$0] }
    }

}

用途:

1
2
3
var mutatingArray = ["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen","Pamela","Jock","Ellie","Bobby","JR"]

swift 3解决方案,遵循@nate cook答案:(如果索引以0开头,请参阅下面的注释)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extension Collection {
    /// Return a copy of `self` with its elements shuffled
    func shuffle() -> [Generator.Element] {
        var list = Array(self)
        list.shuffleInPlace()
        return list
    } }

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 }
        let countInt = count as! Int

    for i in 0..<countInt - 1 {
        let j = Int(arc4random_uniform(UInt32(countInt - i))) + i
            guard i != j else { continue }
            swap(&self[i], &self[j])
        }
    }
}


这是它以最简单的方式完成的。import Gamplaykit到您的vc并使用下面的代码。在xcode 8中测试。

1
2
3
4
5
6
7
8
9
 import GameplayKit

 let array: NSArray = ["Jock","Ellie","Sue Ellen","Bobby","JR","Pamela"]

 override func viewDidLoad() {
    super.viewDidLoad()

    print(array.shuffled())  
}

如果您想从数组中得到一个无序排列的字符串,可以使用下面的代码。

1
2
3
4
5
6
7
8
9
func suffleString() {

    let ShuffleArray = array.shuffled()

    suffleString.text = ShuffleArray.first as? String

    print(suffleString.text!)

}

从维基百科上费希尔-耶茨洗牌的文章中

SWIFT 3.1,4.0

A)纸笔法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func shuffle<T>(_ array:inout [T]){

    var temp = [T]()

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(array.count))
        /*Take the element from array*/
        let elementTaken = array[Int(random)]
        /*Append it to new tempArray*/
        temp.append(elementTaken)
        /*Remove the element from array*/
        array.remove(at: Int(random))

    }
    /* array = tempArray*/
    array = temp
}

b)。现代方法:(杜尔斯滕菲尔德版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func shuffle<T>(_ array:inout [T]){

    var length = array.count

    for _  in array{

        /*Generating random number with length*/
        let random = arc4random_uniform(UInt32(length))
        /*Check before index of two elements not same*/
        if length-1 != Int(random){
            swap(&array[length-1], &array[Int(random)])
        }

        length -= 1
    }
}

Extension:

A)纸笔法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extension Array{

    mutating func shuffled(){

        var temp = [Element]()

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(self.count))
            /*Take the element from array*/
            let elementTaken = self[Int(random)]
            /*Append it to new tempArray*/
            temp.append(elementTaken)
            /*Remove the element from array*/
            self.remove(at: Int(random))

        }
        /* array = tempArray*/
        self = temp
    }
}

b)。现代方法:(杜尔斯滕菲尔德版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
extension Array{

    mutating func shuffled(){

        var length = self.count

        for _  in self{

            /*Generating random number with length*/
            let random = arc4random_uniform(UInt32(length))

            /*Check before index of two elements not same*/

            if length-1 != Int(random){

                /*Swaping elements, If same index then there is no swap*/
               // swap(&self[length-1], &self[Int(random)]) -> Swift 3.0
                self.swapAt(length-1, Int(random)) //-> Swift 4.0

            }

            length -= 1
        }
    }
}

参考文献:

1
2
3
4
5
6
7
8
9
10
/* By using shuffle functions*/
var a = [1,2,3,4,5,6,7,8,9,10]

for _ in 1...10{

    self.shuffle(&a)

    /*For shuffled extension, a.shuffled()*/
    print(a)
}

注:也可以使用空数组。

输出:

[6, 2, 10, 5, 1, 8, 9, 4, 3, 7]

[7, 1, 9, 8, 2, 10, 5, 6, 4, 3]

[8, 9, 6, 10, 5, 2, 7, 4, 3, 1]

[10, 1, 7, 4, 8, 9, 3, 5, 2, 6]

[8, 1, 6, 9, 3, 7, 4, 5, 10, 2]

[4, 3, 7, 9, 1, 5, 8, 6, 10, 2]

[7, 3, 4, 9, 10, 1, 6, 5, 2, 8]

[3, 6, 2, 4, 5, 8, 9, 7, 1, 10]

[5, 1, 2, 10, 6, 9, 7, 3, 8, 4]

[7, 9, 3, 8, 2, 1, 5, 4, 6, 10]

如果有任何疑问,请告诉我,其他的swift版本将很快被检查。


作品!!生物就是要洗牌的阵列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extension Array
{
    /** Randomizes the order of an array's elements. */
    mutating func shuffle()
    {
        for _ in 0..<10
        {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

var organisms = [
   "ant", "bacteria","cougar",
   "dog", "elephant","firefly",
   "goat","hedgehog","iguana"]

print("Original: \(organisms)")

organisms.shuffle()

print("Shuffled: \(organisms)")


您也可以使用通用的swap函数并实现上述fisher-yates:

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

或者更详细:

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


在swift 4.2中,现在有一种方法可以同时使用可变的shuffle和不可变的shuffled。您可以在这里阅读更多关于随机生成和数组的内容。


如果要使用简单的swift for loop函数,请使用此->

1
2
3
4
5
6
7
8
9
10
11
12
13
var arrayItems = ["A1","B2","C3","D4","E5","F6","G7","H8","X9","Y10","Z11"]
var shuffledArray = [String]()

for i in 0..<arrayItems.count
{
    let randomObject = Int(arc4random_uniform(UInt32(items.count)))

    shuffledArray.append(items[randomObject])

    items.remove(at: randomObject)
}

print(shuffledArray)

Swift数组后缀使用扩展->

1
2
3
4
5
6
7
8
extension Array {
    // Order Randomize
    mutating func shuffle() {
        for _ in 0..<count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}


1
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)

这是我使用的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import GameplayKit

extension Collection {
    func shuffled() -> [Iterator.Element] {
        let shuffledArray = (self as? NSArray)?.shuffled()
        let outputArray = shuffledArray as? [Iterator.Element]
        return outputArray ?? []
    }
    mutating func shuffle() {
        if let selfShuffled = self.shuffled() as? Self {
            self = selfShuffled
        }
    }
}

// Usage example:

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

print(numbers) // output example: [2, 3, 5, 4, 1]

print([10,"hi", 9.0].shuffled()) // output example: [hi, 10, 9]


简单例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension Array {
    mutating func shuffled() {
        for _ in self {
            // generate random indexes that will be swapped
            var (a, b) = (Int(arc4random_uniform(UInt32(self.count - 1))), Int(arc4random_uniform(UInt32(self.count - 1))))
            if a == b { // if the same indexes are generated swap the first and last
                a = 0
                b = self.count - 1
            }
            swap(&self[a], &self[b])
        }
    }
}

var array = [1,2,3,4,5,6,7,8,9,10]
array.shuffled()
print(array) // [9, 8, 3, 5, 7, 6, 4, 2, 1, 10]

工作数组扩展(可变和非可变)Swift 4.1/代码9

最上面的答案是不赞成的,所以我自己创建了自己的扩展来在最新版本的swift,swift 4.1(xcode 9)中无序排列数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
extension Array {

// Non-mutating shuffle
    var shuffled : Array {
        let totalCount : Int = self.count
        var shuffledArray : Array = []
        var count : Int = totalCount
        var tempArray : Array = self
        for _ in 0..<totalCount {
            let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
            let randomElement : Element = tempArray.remove(at: randomIndex)
            shuffledArray.append(randomElement)
            count -= 1
        }
        return shuffledArray
    }

// Mutating shuffle
    mutating func shuffle() {
        let totalCount : Int = self.count
        var shuffledArray : Array = []
        var count : Int = totalCount
        var tempArray : Array = self
        for _ in 0..<totalCount {
            let randomIndex : Int = Int(arc4random_uniform(UInt32(count)))
            let randomElement : Element = tempArray.remove(at: randomIndex)
            shuffledArray.append(randomElement)
            count -= 1
        }
        self = shuffledArray
    }
}

调用非变异随机播放[Array] -> [Array]

1
2
3
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

print(array.shuffled)

它以随机顺序打印Array

呼叫变异洗牌[Array] = [Array]

1
2
3
4
5
6
7
var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

array.shuffle()
// The array has now been mutated and contains all of its initial
// values, but in a randomized shuffled order

print(array)

这将按当前顺序打印Array,该顺序已被随机洗牌。

希望这对每个人都有效,如果你有任何问题、建议或意见,请随时提出!


在斯威夫特4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func createShuffledSequenceOfNumbers(max:UInt)->[UInt] {

    var array:[UInt]! = []
    var myArray:[UInt]! = []
    for i in 1...max {
        myArray.append(i)
    }
    for i in 1...max {
        array.append(i)
    }
    var tempArray:[Int]! = []
    for index in 0...(myArray.count - 1) {

        var isNotFinded:Bool = true
        while(isNotFinded){

            let randomNumber = arc4random_uniform(UInt32(myArray.count))
            let randomIndex = Int(randomNumber)

            if(!tempArray.contains(randomIndex)){
                tempArray.append(randomIndex)

                array[randomIndex] = myArray[index]
                isNotFinded = false
            }
        }
    }

    return array
}

这是如何用Swift 3.0中的种子随机移动一个数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)) {
            srand48(seedNumber)
            let number:Int = numericCast(unshuffledCount)
            let r = floor(drand48() * Double(number))

            let d: IndexDistance = numericCast(Int(r))
            guard d != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            swap(&self[firstUnshuffled], &self[i])
        }
    }
}

这是一些在操场上运行的代码。您不需要在实际的Xcode项目中导入达尔文。

1
2
3
4
5
6
7
8
9
10
11
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)


当我将Xcode版本升级到7.4测试版时,它会在"swap(&self[i],&self[j])"处停止。
致命错误:不支持与自身交换位置

I found the reason that i = j (function of swap will exploded)

所以我添加了一个条件如下

1
2
3
if (i != j){
    swap(&list[i], &list[j])
}

哎呀!对我来说没问题。