如何在 Swift 中随机排列数组?

How do I shuffle an array in Swift?

提问人:M-P 提问时间:6/4/2014 最后编辑:FattieM-P 更新时间:11/17/2022 访问量:101411

问:

.shuffle() 和 .shuffled() 是 Swift 的一部分


原始历史问题:

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

阵列 快速 洗牌

评论

13赞 Linus Oleander 6/4/2014
@Mithrandir 那不是真的。在 Ruby 中,人们会选择 .无需实现自己的版本。我猜 OP 正在寻找类似的东西。array.shuffle

答:

-2赞 Dan Hixon 6/4/2014 #1

下面是在 playground 中运行的一些代码。您不需要在实际的 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)

评论

7赞 pjs 6/4/2014
这给出了结果的不均匀分布。它也将是 O(n log n),其中 Fisher-Yates 洗牌将在 O(n) 时间内给出均匀分布的结果。
0赞 Kametrixom 5/31/2015
每次也给出相同的伪随机数,除非你用 like 设置种子drand48()srand48(Int(arc4random()))
663赞 20 revs, 3 users 81%Nate Cook #2

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

斯威夫特 4.2+

shuffleshuffled 是 Swift 4.2 的原生版本。用法示例:

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()

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()

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 上发布)

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

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

shuffle作为突变数组方法

此扩展将允许您就地随机播放可变实例: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作为非突变数组方法

此扩展将允许您检索实例的随机副本: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]

评论

1赞 Airspeed Velocity 4/5/2015
如果您想要 Swift 1.2 中的函数版本,它需要一些更新,因为它已经消失了,并且它的替换 ,现在返回一个,因此约束需要打开。此版本应有效:gist.github.com/airspeedswift/03d07a9dc86fabdc370fcountElementscountT.Index.DistanceC.Index.Distance == Int
2赞 Nate Cook 5/11/2015
这些是实际输出 - Fisher-Yates 应该返回源的无偏随机排列,因此不需要特定元素应该移动。可以保证没有元素移动超过一次,但有时“移动”是到同一个索引。最简单的情况是想一想——应该每次都回来吗?[1, 2].shuffled()[2, 1]
1赞 Carl Smith 6/30/2015
我在 mutating 数组函数的顶部添加了该函数,以防止在传递空数组时收到“致命错误:无法形成 Range with end < start”。if count > 0
3赞 Nate Cook 9/10/2015
@Jan:是的,在交换之前添加。我提交了雷达,但新行为是故意的。guard i != j else { continue }
3赞 Martin R 9/14/2016
实际上,如果集合索引不是从零开始的,例如对于数组切片,则可能会崩溃。 应该是(然后转换为 Swift 3 变得几乎微不足道)。shuffleInPlacefor i in 0..<count - 1for i in startIndex ..< endIndex - 1
27赞 Jean Le Moignan 6/5/2014 #3

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

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

评论

1赞 Jean Le Moignan 8/10/2014
@moby 该函数需要闭包来对元素进行排序。此闭包采用两个参数(elem1、elem2),如果第一个值出现在第二个值之前,则必须返回 true,否则返回 false。如果我们返回一个随机的布尔值......然后我们只是把整个事情混为一谈:)sort
2赞 Jean Le Moignan 8/26/2014
这里有任何数学家来证实或反驳吗?
9赞 Rob 10/20/2014
正如 pjs 在回应另一个非常相似的答案时指出的那样,这不会产生均匀的结果分布。使用 Fisher-Yates Shuffle,如 Nate Cook 的回答所示。
1赞 Alexander 8/9/2016
这是一个聪明的技巧,但就洗牌的质量而言,它很糟糕。首先,这个闭包应该使用 ,因为它目前受到模偏置的影响。其次,输出很大程度上取决于排序算法(如果不查看源代码,我们不知道该算法)。arc4random_uniform()
1赞 markiv 10/6/2017
继续使用这种更简单的方法,这似乎效果很好:collection.sorted { _,_ in arc4random_uniform(1) == 0 }
1赞 Daniel Bauke 10/3/2014 #4

您也可以使用泛型函数并实现上述 Fisher-Yates:swap

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

或不太冗长:

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

评论

2赞 Rob 10/20/2014
这至少会受到此处描述的一个错误的严重偏离,即值总是从其原始位置交换。这可以通过 解决。此外,在 FY 中,您通常从 down 迭代到 (或者如果您从 to 迭代,则选择索引,就像 Nate 在接受的答案中显示的那样)。请参阅 Fisher-Yates 讨论的现代算法部分let rnd = Int(arc4random_uniform(UInt32(idx + 1)))arr.count - 110arr.count - 1
3赞 iliketopgun 4/9/2015 #5

这是我使用的:

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
}
8赞 Chris Wagner 6/15/2015 #6

Nate 的算法为例,我想看看 Swift 2 和协议扩展会是什么样子。

这就是我想出的。

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

现在,任何人都可以使用这些方法,因为它用作MutableCollectionTypeIntIndex

135赞 rickster 6/16/2015 #7

编辑:正如其他答案所指出的,Swift 4.2 最终在标准库中添加了随机数生成功能,并完成了数组洗牌。

但是,GameplayKit 中的 / suite 对于新协议仍然有用——如果您向 GameplayKit RNG 添加扩展以符合新的标准库协议,则可以轻松获得:GKRandomGKRandomDistributionRandomNumberGenerator

  • 可发送的 RNG(在需要测试时可以重现“随机”序列)
  • 为了速度而牺牲鲁棒性的 RNG
  • 产生不均匀分布的 RNG

...并且仍然使用 Swift 中新的“原生”随机 API。

这个答案的其余部分涉及此类 RNG 和/或它们在旧版 Swift 编译器中的使用。


这里已经有一些很好的答案,也有一些很好的说明,说明为什么如果你不小心,编写自己的随机播放很容易出错。

在 iOS 9、macOS 10.11 和 Apple tvOS 9(或更高版本)中,您无需编写自己的内容。GameplayKit 中有一个高效、正确的 Fisher-Yates 实现(尽管它的名字不仅适用于游戏)。

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

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

如果您希望能够复制一个或一系列随机排序,请选择并设定一个特定的随机源;例如

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

在 iOS 10 / macOS 10.12 / tvOS 10 中,还有一个方便的语法,可以通过扩展程序进行随机播放。当然,当你使用 Swift 时,这有点麻烦(它会在返回 Swift 时失去它的元素类型):NSArrayArray

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

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

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()

评论

6赞 Richard Venable 10/26/2015
让我想知道在 GameplayKit 中还可以找到哪些我从未探索过的有用实用程序!
6赞 rickster 10/26/2015
图搜索、树搜索、规则系统......很多东西对游戏设计和其他方面都有帮助。
5赞 Evan Pon 11/17/2016
在 Swift 3/iOS 10 中,这已更改为:let shuffled = lcg.arrayByShufflingObjects(in: array)
-3赞 米米米 8/26/2015 #8

当我将 xCode 版本升级到 7.4 beta 时,它停在“swap(&self[i], &self[j])”。
致命错误:不支持将位置与自身交换

我找到了 i = j 的原因(swap 的函数会爆炸)

所以我添加一个条件,如下所示

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

你!这对我来说没关系。

评论

0赞 Mogsdad 8/26/2015
这似乎是对克里斯答案的评论,而不是对原始问题的回答。
2赞 Imanou Petit 12/15/2015 #9

在 Swift 3 中,如果你想对数组进行随机排序,或者从数组中获取一个新的随机数组,AnyIterator 可以帮到你。这个想法是从你的数组创建一个索引数组,用一个实例和 swap(_:_:) 函数洗牌这些索引,并将这个实例的每个元素与数组的相应元素映射。AnyIteratorAnyIterator


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

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

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

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

}

用法:

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

作为前面代码的替代方法,您可以在扩展中创建一个函数,以便就地随机排列数组:shuffle()Array

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

}

用法:

var mutatingArray = ["Jock", "Ellie", "Sue Ellen", "Bobby", "JR", "Pamela"]
mutatingArray.shuffle()
print(mutatingArray) // may print ["Sue Ellen", "Pamela", "Jock", "Ellie", "Bobby", "JR"]
31赞 bluenowhere 3/17/2016 #10

Swift 2.0 中,GameplayKit 可能会派上用场!(iOS9 或更高版本支持)

import GameplayKit

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

评论

5赞 Lope 4/29/2017
导入 GameplayKit 只是为了获得随机数组听起来不是一个好主意
3赞 Abizern 10/7/2017
为什么?它是系统的一部分,不会添加到二进制文件中。
3赞 JRG-Developer 11/14/2017
还可以将导入范围限定为简单import GameplayKit.GKRandomSource
2赞 Anson Yao 8/26/2016 #11

Swift 3 解决方案,以下@Nate Cook 答案:(如果索引以 0 开头,请工作,请参阅下面的注释)

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

评论

1赞 Martin R 9/14/2016
如果集合索引确实从 0 开始,例如对于数组切片,这可能会崩溃。尝试运行几次。– 有关正确的解决方案,请参阅 stackoverflow.com/a/37843901/1187415var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()
2赞 Joe 10/3/2016 #12

这就是它以最简单的方式完成的方式。添加到您的 VC 并使用以下代码。在 Xcode 8 中测试。import Gamplaykit

 import GameplayKit

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

 override func viewDidLoad() {
    super.viewDidLoad()

    print(array.shuffled())  
}

如果你想从数组中获取一个随机的字符串,你可以使用下面的代码..

func suffleString() {

    let ShuffleArray = array.shuffled()

    suffleString.text = ShuffleArray.first as? String

    print(suffleString.text!)

}
7赞 Kaz Yoshikawa 10/24/2016 #13

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

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

}
0赞 Tayo119 12/15/2016 #14

这是在 Swift 3.0 中用种子洗牌一个数组的方法。

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])
        }
    }
}
0赞 Rohit Sisodia 6/5/2017 #15
let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
6赞 Martin R 6/9/2017 #16

这是 Nate 为 Swift 4 (Xcode 9) 实现的 Fisher-Yates shuffle 的一个版本。

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 == IndexCollection
  • 交换元素必须通过调用集合来完成, 比较 SE-0173 添加 MutableCollection.swapAt(_:_:)swapAt()
  • Element是 的别名。Iterator.Element
0赞 Daniel Illescas 6/25/2017 #17

这是我使用的:

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]
0赞 Bobby 7/3/2017 #18

简单示例:

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]
1赞 Vimal 12/8/2017 #19

工程!!。有机体是要洗牌的阵列。

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)")
4赞 Sergei 1/3/2018 #20

斯威夫特 4在 for 循环中随机排列数组的元素,其中 i 是混合比率

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

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
        }
    }
}
1赞 Noah Wilder 3/22/2018 #21

工作阵列扩展(突变和非突变)

斯威夫特 4.1 / Xcode 9

最上面的答案已被弃用,所以我自己创建了自己的扩展,以便在最新版本的 Swift Swift 4.1 (Xcode 9) 中随机播放数组:

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]

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]

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


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

1赞 ali khezri 5/17/2018 #22

在 SWIFT 4 中

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
}
2赞 leogdion 6/6/2018 #23

Swift 4.2 中,现在有一种既可以进行可变洗牌又可以进行不可变洗的方法。你可以在这里阅读更多关于随机生成和数组的信息。

1赞 Rahul Singha Roy 6/27/2018 #24

如果你想使用简单的 Swift For 循环函数,请使用这个 ->

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 Array suffle

extension Array {
    // Order Randomize
    mutating func shuffle() {
        for _ in 0..<count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}
10赞 swift-lynx 5/22/2019 #25

从 swift 4.2 开始,有两个方便的功能:

// shuffles the array in place
myArray.shuffle()

// generates a new array with shuffled elements of the old array
let newArray = myArray.shuffled()