如何在 Swift 中打乱数组?
Posted
技术标签:
【中文标题】如何在 Swift 中打乱数组?【英文标题】:How do I shuffle an array in Swift? 【发布时间】:2014-07-24 11:00:09 【问题描述】:如何在 Swift 中随机化或打乱数组中的元素?例如,如果我的阵列由 52 张扑克牌组成,我想洗牌阵列以便洗牌。
【问题讨论】:
这不是特定于任何语言的。只需应用任何洗牌算法... @Mithrandir 这不是真的。在 Ruby 中,可以选择array.shuffle
。无需实现您自己的版本。我猜 OP 正在寻找类似的东西。
【参考方案1】:
此答案详细说明了如何在 Swift 4.2+ 中使用快速且统一的算法(Fisher-Yates)进行洗牌,以及如何在 Swift 的各个早期版本中添加相同的功能。每个 Swift 版本的命名和行为与该版本的变异和非变异排序方法相匹配。
斯威夫特 4.2+
shuffle
和 shuffled
从 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]
【讨论】:
如果你想要 Swift 1.2 中的函数版本,它需要一些更新,因为countElements
已经消失,它的替换,count
,现在返回一个 T.Index.Distance
所以约束需要在C.Index.Distance == Int
上。这个版本应该可以工作:gist.github.com/airspeedswift/03d07a9dc86fabdc370f
这些是实际输出——Fisher-Yates 应该返回源的无偏随机排列,因此不要求特定元素应该移动。 是保证没有元素移动超过一次,但有时“移动”是相同的索引。最简单的情况是考虑[1, 2].shuffled()
——是否应该每次都返回[2, 1]
?
我在 mutating array 函数的顶部添加了if count > 0
,以防止在传递空数组时收到“致命错误:Can't form Range with end
@Jan:是的,在交换之前添加guard i != j else continue
。我提交了雷达,但新行为是故意的。
实际上shuffleInPlace
可能会在集合索引不从零开始时崩溃,例如对于数组切片。 for i in 0..<count - 1
应该是 for i in startIndex ..< endIndex - 1
(然后转换到 Swift 3 变得几乎是微不足道的)。【参考方案2】:
编辑:如其他答案所述,Swift 4.2 finally 将随机数生成添加到标准库中,并完成了数组改组。
但是,GameplayKit 中的 GKRandom
/ GKRandomDistribution
套件仍然可以与新的 RandomNumberGenerator
协议一起使用 — 如果您向 GameplayKit RNG 添加扩展以符合新的标准库协议,您可以轻松获得:
...并且仍然使用 Swift 中不错的新“原生”随机 API。
此答案的其余部分涉及此类 RNG 和/或它们在较旧的 Swift 编译器中的使用。
这里已经有一些很好的答案,以及一些很好的说明,说明为什么如果你不小心编写自己的 shuffle 会容易出错。
在 ios 9、macOS 10.11 和 tvOS 9(或更高版本)中,您不必自己编写。 GameplayKit 中有an efficient, correct implementation of Fisher-Yates(尽管名称如此,但它不仅仅用于游戏)。
如果您只想要一个独特的随机播放:
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: array)
如果您希望能够复制 shuffle 或一系列 shuffle,请选择并播种特定的随机源;例如
let lcg = GKLinearCongruentialRandomSource(seed: mySeedValue)
let shuffled = lcg.arrayByShufflingObjects(in: array)
在 iOS 10 / macOS 10.12 / tvOS 10 中,还有一个方便的语法用于通过 NSArray
上的扩展名进行改组。当然,当您使用 Swift Array
时,这有点麻烦(并且在返回 Swift 时它会丢失其元素类型):
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()
【讨论】:
让我想知道 GameplayKit 中还有哪些我从未探索过的有用实用程序! 图形搜索、树搜索、规则系统...lots of stuff这对游戏设计和其他方面都有帮助。 在 Swift 3/iOS 10 中,这已更改为:let shuffled = lcg.arrayByShufflingObjects(in: array)
【参考方案3】:
在 Swift 2.0 中,GameplayKit 可能会派上用场! (iOS9 或更高版本支持)
import GameplayKit
func shuffle()
array = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(array)
【讨论】:
导入 GameplayKit 只是为了获得洗牌数组听起来不是个好主意 为什么?它是系统的一部分,不会添加到二进制文件中。 您还可以将导入范围简单地设置为import GameplayKit.GKRandomSource
【参考方案4】:
这里可能有点短:
sorted(a) _, _ in arc4random() % 2 == 0
【讨论】:
@mobysort
函数需要一个闭包来对元素进行排序。这个闭包有两个参数(elem1,elem2),如果第一个值应该出现在第二个值之前,则必须返回 true,否则返回 false。如果我们返回一个随机布尔值......那么我们只是把整个事情搞混了:)
有没有数学家来证实或证伪?
正如 pjs 在回应另一个非常相似的答案时指出的那样,这将不会生成均匀分布的结果。使用Fisher-Yates Shuffle,如 Nate Cook 的回答所示。
这是一个聪明的技巧,但在随机播放的质量方面却很糟糕。一方面,这个闭包应该使用arc4random_uniform()
,因为它目前受到模偏差的影响。其次,输出很大程度上依赖于排序算法(不看源码我们不知道)。
继续使用这种更简单的方法,这似乎工作得很好:collection.sorted _,_ in arc4random_uniform(1) == 0
【参考方案5】:
采用Nate's 算法,我想看看它在 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
现在,任何MutableCollectionType
都可以使用这些方法,因为它使用Int
作为Index
【讨论】:
【参考方案6】:在我的例子中,我在交换 Array 中的对象时遇到了一些问题。然后我挠了挠头,开始重新发明***。
// 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
【讨论】:
【参考方案7】:这是 Swift 4 的 Nate's implementation of the 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
变化是:
约束Indices.Iterator.Element == Index
现在是一部分
的Collection
协议,不需要强加于
不再扩展。
交换元素必须通过在集合上调用swapAt()
来完成,
比较SE-0173 Add MutableCollection.swapAt(_:_:)
。
Element
是 Iterator.Element
的别名。
【讨论】:
【参考方案8】:斯威夫特 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
【讨论】:
【参考方案9】:这是我用的:
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
【讨论】:
【参考方案10】:从 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()
【讨论】:
【参考方案11】:Swift 3 解决方案,遵循@Nate Cook 的回答:(如果索引以 0 开头,则工作,请参阅下面的 cmets)
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])
【讨论】:
如果集合索引确实从 0 开始,这可能会崩溃,例如对于数组切片。尝试多次运行var a = [1, 2, 3, 4, 5, 6][3..<6]; a.shuffleInPlace()
。 – 请参阅***.com/a/37843901/1187415 以获得正确的解决方案。【参考方案12】:
这是以最简单的方式完成的。import 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!)
【讨论】:
【参考方案13】:在 Swift 3 中,如果您想在适当的位置打乱数组或从数组中获取新的打乱数组,AnyIterator
可以为您提供帮助。这个想法是从你的数组中创建一个索引数组,用AnyIterator
实例和swap(_:_:)
函数对这些索引进行洗牌,并将这个AnyIterator
实例的每个元素映射到数组的对应元素。
以下 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"]
您可以重构之前的代码并在 Array
扩展中创建一个 shuffled()
函数,以便从数组中获取新的打乱数组:
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: []
作为前面代码的替代方案,您可以在 Array
扩展内创建一个 shuffle()
函数,以便在适当的位置打乱数组:
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"]
【讨论】:
【参考方案14】:如果你想使用简单的 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()
【讨论】:
【参考方案15】:您也可以使用通用swap
函数并实现提到的Fisher-Yates:
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)))])
【讨论】:
这至少会遇到一个严重的off by one错误described here,其中一个值总是从其原始位置交换.这可以通过let rnd = Int(arc4random_uniform(UInt32(idx + 1)))
解决。此外,在 FY 中,您通常从 arr.count - 1
迭代到 1
(或者如果您从 0
迭代到 arr.count - 1
,您会选择 Nate 在接受的答案中显示的索引)。请参阅 Fisher-Yates 讨论的 Modern Algorithm section。【参考方案16】:
有效!!。生物体是要洗牌的数组。
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)")
【讨论】:
【参考方案17】:工作数组扩展(变异和非变异)
斯威夫特 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
,该顺序已经随机打乱。
希望这对大家有用,如果您有任何问题、建议或 cmets,请随时提问!
【讨论】:
【参考方案18】:在 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
【讨论】:
【参考方案19】:在 Swift 4.2 中,现在有一个用于 mutable shuffle
和 immutable shuffled
的方法。你可以阅读更多关于随机生成和数组的内容here。
【讨论】:
【参考方案20】:这是在 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])
【讨论】:
【参考方案21】:let shuffl = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: arrayObject)
【讨论】:
【参考方案22】:这是我用的:
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]
【讨论】:
【参考方案23】:简单示例:
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]
【讨论】:
【参考方案24】:这里有一些在 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)
【讨论】:
这给出了结果的非均匀分布。它也将是 O(n log n),其中 Fisher-Yates shuffle 将在 O(n) 时间内给出均匀分布的结果。 另外,drand48()
每次都会给出相同的伪随机数,除非您使用 srand48(Int(arc4random()))
设置种子【参考方案25】:
当我将 xCode 版本升级到 7.4 beta 时,它停在“swap(&self[i], &self[j])”。 致命错误:不支持与自身交换位置
我找到了i = j的原因(swap函数会爆炸)
所以我添加如下条件
if (i != j)
swap(&list[i], &list[j])
耶!对我来说没问题。
【讨论】:
这似乎是对Chris's answer 的评论,而不是对原始问题的回答。以上是关于如何在 Swift 中打乱数组?的主要内容,如果未能解决你的问题,请参考以下文章
如何在给定范围内创建一个随机打乱数字的 int 数组 [重复]