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


原历史问题:

我如何随机或洗牌在Swift数组中的元素?例如,如果我的数组包含52张扑克牌,我想要洗牌数组以洗牌牌组。


当前回答

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

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

调用非突变Shuffle [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)

这将以随机顺序打印数组。


调用Shuffle [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) 

这将打印数组的当前顺序,该顺序已经被随机打乱。


希望这对每个人都有用,如果你有任何问题,建议或评论,请随时提问!

其他回答

这里有一些可能更短的内容:

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

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

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

这些变化是:

约束indexes . iterator . element == Index现在是部分 的收集协议,并且不需要强加于 扩展了。 交换元素必须通过调用集合上的swapAt()来完成, 添加mutableccollection . swapat(_:_:)。 Element是Iterator.Element的别名。

工作! !生物体是要洗牌的数组。

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

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

这是最简单的方法。导入Gamplaykit到你的VC中,使用下面的代码。在Xcode 8中测试。

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

}