मैं स्विफ्ट में एक सरणी फेरबदल कैसे कर सकता हूं?


305

मैं स्विफ्ट में एक सरणी के भीतर तत्वों को कैसे यादृच्छिक या फेरबदल कर सकता हूं? उदाहरण के लिए, यदि मेरे सरणी में 52 प्लेइंग कार्ड हैं, तो मैं डेक को फेरबदल करने के लिए सरणी में फेरबदल करना चाहता हूं ।


2
यह किसी भी भाषा के लिए विशिष्ट नहीं है। बस किसी भी फेरबदल एल्गोरिथ्म लागू ...
गेब्रियल पेट्रोनेला

8
@ मिथिंदिर यह सच नहीं है। रूबी में एक के लिए जाना होगा array.shuffle। अपने स्वयं के संस्करण को लागू करने की कोई आवश्यकता नहीं है। मुझे लगता है कि ओपी कुछ इसी तरह की तलाश में था।
लिनस ओलियंडर

1
हालांकि, सावधान रहें, कार्ड के डेक को फेरबदल करने के लिए किसी भी फेरबदल एल्गोरिथ्म का उपयोग न करें।
njzk2

जवाबों:


626

यह उत्तर ब्योरा देता है कि स्विफ्ट 4.2+ में एक तेज और समान एल्गोरिथ्म (फिशर-येट्स) के साथ फेरबदल कैसे करें और स्विफ्ट के विभिन्न पिछले संस्करणों में समान सुविधा कैसे जोड़ें। प्रत्येक स्विफ्ट संस्करण के लिए नामकरण और व्यवहार उस संस्करण के लिए परिवर्तनशील और गैर-सॉर्टिंग सॉर्टिंग विधियों से मेल खाता है।

स्विफ्ट 4.2+

shuffleऔर shuffledस्विफ्ट 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]

स्विफ्ट 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
    }
}

ऊपर दिए गए 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
    }
}

ऊपर दिए गए 4.2 उदाहरणों के समान उपयोग।


स्विफ्ट 2

(अप्रचलित भाषा: जुलाई 2018 से शुरू होने वाले आईट्यून्स कनेक्ट पर प्रकाशित करने के लिए आप स्विफ्ट 2.x का उपयोग नहीं कर सकते हैं)

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 से शुरू होने वाले iTunes कनेक्ट पर प्रकाशित करने के लिए स्विफ्ट 1.x का उपयोग नहीं कर सकते हैं)

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
यदि आप स्विफ्ट 1.2 में फ़ंक्शन संस्करण चाहते हैं, तो उसे अपडेट करने की थोड़ी आवश्यकता है countElements, और यह प्रतिस्थापन है count, अब एक वापसी T.Index.Distanceकी जरूरत है ताकि बाधा को चालू किया जा सके C.Index.Distance == Int। यह संस्करण काम करना चाहिए: gist.github.com/airspeedswift/03d07a9dc86fabdc370f
Airspeed वेग

2
वे वास्तविक आउटपुट हैं- फिशर-येट्स को स्रोत के एक निष्पक्ष यादृच्छिक क्रमांकन को वापस करना चाहिए, इसलिए किसी विशेष तत्व को स्थानांतरित करने की आवश्यकता नहीं है। इस बात की गारंटी है कि कोई भी तत्व एक से अधिक बार नहीं चलता है, लेकिन कभी-कभी "चाल" उसी सूचकांक में होती है। सबसे आसान मामला यह है कि क्या हर बार [1, 2].shuffled()वापसी करने के बारे में सोचना चाहिए [2, 1]?
नैट कुक

1
मैंने if count > 0एक "घातक त्रुटि: न समाप्त होने वाली श्रेणी के साथ सीमा नहीं बना सकता है जब यह एक खाली सरणी को पारित किया जाता है, तो रोकने के लिए, मैं म्यूटिंग सरणी फ़ंक्शन के शीर्ष पर जोड़ा गया ।
कार्ल स्मिथ

3
@ जान: हां, guard i != j else { continue }स्वैप से पहले जोड़ें । मैंने एक राडार दायर किया, लेकिन नया व्यवहार जानबूझकर किया गया है।
नैट कुक

3
वास्तव में shuffleInPlaceदुर्घटना हो सकती है अगर संग्रह सूचक शून्य पर शुरू नहीं होते हैं, उदाहरण के लिए एक सरणी टुकड़ा के लिए। for i in 0..<count - 1 होना चाहिए for i in startIndex ..< endIndex - 1(और फिर स्विफ्ट 3 में रूपांतरण लगभग तुच्छ हो जाता है)।
मार्टिन आर।

131

संपादित करें: जैसा कि अन्य उत्तरों में उल्लेख किया गया है, स्विफ्ट 4.2 अंत में मानक पुस्तकालय में यादृच्छिक संख्या पीढ़ी जोड़ता है, जो सरणी फेरबदल के साथ पूरा होता है।

हालाँकि, GameplayKit में GKRandom/ GKRandomDistributionसूट अभी भी नए RandomNumberGeneratorप्रोटोकॉल के साथ उपयोगी हो सकता है - यदि आप GameplayKit RNGs में एक्सटेंशन जोड़ते हैं, तो नए मानक लाइब्रेरी प्रोटोकॉल के अनुरूप, आप आसानी से प्राप्त कर सकते हैं:

  • भेजने योग्य आरएनजी (जो परीक्षण के लिए आवश्यक होने पर "यादृच्छिक" अनुक्रम को पुन: उत्पन्न कर सकते हैं)
  • RNG जो गति के लिए मजबूती का त्याग करते हैं
  • RNG जो गैर-समान वितरण का उत्पादन करते हैं

... और अभी भी स्विफ्ट में अच्छे नए "देशी" यादृच्छिक एपीआई का उपयोग करें।

इस जवाब के बाकी हिस्सों में इस तरह के आरएनजी और / या पुराने स्विफ्ट कंपाइलर में उनके उपयोग की चिंता है।


यहां पहले से ही कुछ अच्छे उत्तर हैं, साथ ही कुछ अच्छे उदाहरण भी हैं कि यदि आप सावधान नहीं हैं तो अपने स्वयं के फेरबदल को लिखने में त्रुटि हो सकती है।

IOS 9 में, macOS 10.11, और tvOS 9 (या बाद में), आपको अपना खुद का लिखना नहीं है। गेमप्लेकिट में फिशर-येट्स का एक कुशल, सही कार्यान्वयन है (जो नाम के बावजूद, केवल खेलों के लिए नहीं है)।

यदि आप केवल एक अनोखा फेरबदल चाहते हैं:

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 में, पर विस्तार के माध्यम से फेरबदल के लिए एक सुविधा सिंटैक्स भी है NSArray। बेशक, यह थोड़ा बोझिल है जब आप स्विफ्ट का उपयोग कर रहे हैं Array(और यह स्विफ्ट पर वापस आने पर अपना तत्व प्रकार खो देता है):

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

लेकिन इसके लिए एक टाइप-सेविंग स्विफ्ट रैपर बनाना बहुत आसान है:

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
मुझे आश्चर्य होता है कि गेमप्लेकिट में अन्य सहायक उपयोगिताओं को क्या पाया जा सकता है जो मैंने कभी नहीं खोजा है!
रिचर्ड वेनटेबल

6
ग्राफ सर्च, ट्री सर्च, रूल सिस्टम ... बहुत सारा सामान जो गेम डिजाइन और अन्यथा दोनों में सहायक होता है।
रिकस्टर

5
स्विफ्ट 3 / iOS 10 में, इसे बदल दिया गया है:let shuffled = lcg.arrayByShufflingObjects(in: array)
इवान पोन

30

में स्विफ्ट 2.0 , GameplayKit बचाव के लिए आ सकता है! ( iOS9 या बाद के संस्करण द्वारा समर्थित )

import GameplayKit

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

5
आयात GameplayKit सिर्फ फेरबदल सरणी पाने के लिए एक महान विचार की तरह आवाज नहीं करता है
लोप

3
क्यों? यह सिस्टम का हिस्सा है, बाइनरी में शामिल नहीं होता है।
अबिज़र्न

3
तुम भी आयात करने के लिए गुंजाइश कर सकते हैंimport GameplayKit.GKRandomSource
JRG-Developer

26

यहाँ कुछ संभवतः थोड़ा छोटा है:

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

1
@ moby sortफ़ंक्शन को तत्वों को ऑर्डर करने के लिए क्लोजर की आवश्यकता होती है। यह क्लोजर दो पैरामीटर (elem1, elem2) लेता है और सही होना चाहिए अगर पहला मान दूसरे मूल्य से पहले प्रकट होना चाहिए, और अन्यथा गलत। अगर हम बदले में एक यादृच्छिक बूलियन लौटाते हैं ... तो हम पूरी चीज़ को
मिलाते हैं

2
किसी भी गणितज्ञ की पुष्टि करने या उसे अस्वीकार करने के लिए यहां?
जीन ले मोइगन

9
जैसा कि पीजे ने एक और समान जवाब के जवाब में कहा है, इससे परिणामों का समान वितरण नहीं होगा । नैट कुक के जवाब में दिखाए गए अनुसार फिशर-येट्स शफल का उपयोग करें ।
रोब

1
यह एक चतुर चाल है, लेकिन फेरबदल की गुणवत्ता के मामले में संक्षिप्त है। एक के लिए, इस बंद का उपयोग करना चाहिए, क्योंकि arc4random_uniform()यह वर्तमान में modulo पूर्वाग्रह के अधीन है। दूसरे, आउटपुट छँटाई एल्गोरिथ्म पर बहुत निर्भर करता है (जो स्रोत को देखे बिना हमें ज्ञात नहीं है)।
अलेक्जेंडर -

1
इस सरल दृष्टिकोण के साथ, यह काफी अच्छी तरह से काम करने लगता है: collection.sorted { _,_ in arc4random_uniform(1) == 0 }
9

7

नैट का एल्गोरिथ्म लेते हुए मैं यह देखना चाहता था कि स्विफ्ट 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
    }
}

अब, कोई भी MutableCollectionTypeइन विधियों का उपयोग कर सकता है जो इसे Intएक के रूप में उपयोग करता हैIndex


6

मेरे मामले में, मुझे ऐरे में वस्तुओं की अदला-बदली की कुछ समस्याएं थीं। फिर मैंने अपना सिर खुजलाया और पहिए को फिर से लगाने के लिए चला गया।

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

}

5

इस का एक संस्करण है फिशर-येट्स फेरबदल की नैट के कार्यान्वयन के लिए स्विफ्ट 4 (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
    }
}

परिवर्तन हैं:

  • बाधा Indices.Iterator.Element == Indexअब Collectionप्रोटोकॉल का हिस्सा है , और विस्तार पर अब और लगाए जाने की आवश्यकता नहीं है।
  • swapAt()संग्रह पर कॉल करके तत्वों का आदान-प्रदान किया जाना चाहिए , SE-0173 जोड़ें कीMutableCollection.swapAt(_:_:) तुलना करें ।
  • Elementके लिए एक उपनाम है Iterator.Element

3

यही है वह जो मेरे द्वारा उपयोग किया जाता है:

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
}

3

स्विफ्ट 4 एक लूप में सरणी के तत्वों को फेरबदल करें जहां मैं मिश्रण अनुपात है

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

या विस्तार के साथ इंट

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

2

स्विफ्ट 3 सॉल्यूशन, @Nate कुक जवाब के बाद: (कार्य यदि इंडेक्स 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
यदि यह संग्रह सूचकांकों को 0 पर प्रारंभ करता है, तो सरणी स्लाइस के लिए क्रैश हो सकता है। var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()कई बार चलाने की कोशिश करें । - सही समाधान के लिए stackoverflow.com/a/37843901/1187415 देखें ।
मार्टिन आर।

2

यह कैसे एक सरल तरीके से किया जाता है। import Gamplaykitअपने वीसी के पास और नीचे दिए गए कोड का उपयोग करें। 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!)

}

2

स्विफ्ट 3 के साथ, यदि आप जगह में एक सरणी फेरबदल करना चाहते हैं या एक सरणी से एक नया फेरबदल सरणी प्राप्त करना चाहते हैं, तो आपकी AnyIteratorमदद कर सकता है। विचार यह है कि अपने सरणी से सूचकांकों की एक सरणी बनाएं, उन सूचकांकों को एक AnyIteratorउदाहरण और swap(_:_:)फ़ंक्शन के साथ फेरबदल करें और इस AnyIteratorउदाहरण के प्रत्येक तत्व को सरणी के संगत तत्व के साथ मैप करें ।


निम्न खेल का मैदान कोड दिखाता है कि यह कैसे काम करता है:

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

1

आप जेनेरिक 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
यह बहुत ही कम से कम, एक त्रुटि से गंभीर रूप से ग्रस्त है, जिसका वर्णन यहां किया गया है, जिसमें एक मूल्य हमेशा अपनी मूल स्थिति से अदला-बदली होता है। यह के साथ remedied है let rnd = Int(arc4random_uniform(UInt32(idx + 1)))। इसके अलावा, वित्त वर्ष में, आप आम तौर पर arr.count - 1नीचे से 1(या यदि आप से पुनरावृति 0करते हैं arr.count - 1, तो आप स्वीकार किए गए उत्तर में नैट शो जैसे सूचकांक चुनते हैं)। फिशर-येट्स चर्चा के आधुनिक एल्गोरिथ्म अनुभाग देखें ।
रोब

1

काम करता है !!। जीवों को फेरबदल करने के लिए सरणी है।

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


0

यह कैसे स्विफ्ट 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

यही है वह जो मेरे द्वारा उपयोग किया जाता है:

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

सरल उदाहरण:

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]

0

कार्य सरणी विस्तार (परिवर्तन और गैर-परिवर्तन)

स्विफ्ट 4.1 / Xcode 9

शीर्ष उत्तर पदावनत है, इसलिए मैंने स्विफ्ट, स्विफ्ट 4.1 (एक्सकोड 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अपने वर्तमान क्रम में प्रिंट करता है, जिसे पहले से ही बेतरतीब ढंग से बदल दिया गया है।


आशा है कि यह हर किसी के लिए काम करता है, यदि आपके कोई प्रश्न, सुझाव, या टिप्पणी हैं, तो बेझिझक पूछें!


0

स्विफ्ट 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
}

0

यदि आप साधारण स्विफ्ट फॉर लूप फ़ंक्शन का उपयोग करना चाहते हैं तो इसका उपयोग करें ->

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)

एक्सटेंशन -> का उपयोग करके स्विफ्ट ऐरे को संभालें

extension Array {
    // Order Randomize
    mutating func shuffle() {
        for _ in 0..<count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

0

तेजी से 4.2 के रूप में दो काम कर रहे हैं:

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

तथा

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

-2

यहाँ कुछ कोड है जो खेल के मैदान में चलता है। आपको वास्तविक एक्सकोड परियोजना में डार्विन को आयात करने की आवश्यकता नहीं होगी।

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

इसके अलावा drand48()एक ही छद्म यादृच्छिक संख्या हर देता है, जब तक आप की तरह के साथ एक बीज सेटsrand48(Int(arc4random()))
Kametrixom

-3

जब मैं xCode संस्करण को 7.4 बीटा में अपग्रेड करता हूं तो यह "स्वैप (और स्वयं [i], और स्व [j])" पर रुक जाता है।
घातक त्रुटि: किसी स्थान को स्वयं से स्वैप करना समर्थित नहीं है

मैंने पाया कि i = j (स्वैप का कार्य विस्फोट होगा)

इसलिए मैं नीचे एक शर्त जोड़ता हूं

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

YA! मेरे लिए ठीक है।


यह क्रिस के उत्तर पर टिप्पणी प्रतीत होता है , मूल प्रश्न का उत्तर नहीं।
मोगसाद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.