Shuffle array swift 3

Как я могу преобразовать функцию ниже в swift 3 ? В настоящее время получение Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance' .

 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 } for i in 0..<count - 1 { //error takes place here let j = Int(arc4random_uniform(UInt32(count - i))) + i guard i != j else { continue } swap(&self[i], &self[j]) } } } 

ссылка: https://stackoverflow.com/a/24029847/5222077

count возвращает IndexDistance который является типом, описывающим расстояние между двумя индексами коллекции. IndexDistance должен быть SignedInteger , но не должен быть Int и может отличаться от Index . Поэтому невозможно создать диапазон 0.. .

Решение состоит в том, чтобы использовать startIndex и endIndex вместо 0 и count :

 extension MutableCollection where Index == Int { /// Shuffle the elements of `self` in-place. mutating func shuffle() { // empty and single-element collections don't shuffle if count < 2 { return } for i in startIndex ..< endIndex - 1 { let j = Int(arc4random_uniform(UInt32(endIndex - i))) + i if i != j { swap(&self[i], &self[j]) } } } } 

Другим преимуществом является то, что это также корректно работает с срезами массива (где индекс первого элемента необязательно равен нулю).

Обратите внимание, что согласно новому «Руководству по дизайну Swift API» , shuffle() является «правильным» именем для мутирующего метода тасования и shuffled() для не мутирующего аналога, который возвращает массив:

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

Обновление: добавлена ​​(еще более общая) версия Swift 3. Как перетасовать массив в Swift? в это время.


Для Swift 4 (Xcode 9) нужно заменить вызов функции swap() вызовом метода swapAt() коллекции. Также ограничение на тип Index больше не требуется:

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

См. SE-0173. Добавьте MutableCollection.swapAt(_:_:) для получения дополнительной информации о swapAt .


С Swift 4.2 (Xcode 10, в настоящее время в бета-версии) с реализацией SE-0202 Random Unification , shuffle() и shuffled() являются частью стандартной библиотеки Swift.

В Gamekit происходит перетасовка рыбаков и ятов:

 import GameKit let unshuffledArray = [1,2,3,4] let shuffledArray = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: unshuffledArray) print(shuffledArray) 

Вы также можете передавать и хранить случайное семя, поэтому вы получаете одну и ту же последовательность псевдослучайных значений тасования каждый раз, когда вы поставляете одно и то же семя, если вам нужно воссоздать симуляцию.

 import GameKit let unshuffledArray = [1,2,3,4] let randomSource = GKLinearCongruentialRandomSource(seed: 1) let shuffledArray = randomSource.arrayByShufflingObjects(in: unshuffledArray) //Always [1,4,2,3] print(shuffledArray) 

Я бы предложил просто перетасовывать массивы вместо того, чтобы распространять это на коллекции в целом:

 extension Array { mutating func shuffle () { for i in (0.. 

Вы можете использовать NSArray Extension из frameworks GameplayKit для этого:

 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] 
  • Правильно Разбор JSON в Swift 3
  • Есть ли способ установить связанные объекты в Swift?
  • Как вы используете String.substringWithRange? (или, как работают диапазоны в Swift?)
  • Как отправить dispatch_sync, dispatch_async, dispatch_after и т. Д. В Swift 3, Swift 4 и дальше?
  • generics как параметры для закрытия в быстрых
  • Использование вывода Swift 3 @objc в режиме Swift 4 устарело?
  • Как управлять расстоянием между строками в UILabel
  • Как я могу атомизировать приращение переменной в Swift?
  • Сохранение значений в завершенииHandlers - Swift
  • Как использовать NSToolBar в Xcode 6 и Storyboard?
  • Вызов метода фабрики Swift с использованием точечной нотации?
  • Давайте будем гением компьютера.