随机排列数组 swift 3 [英] Shuffle array swift 3
问题描述
如何将下面的函数转换为 swift 3
?当前获得 二元运算符 '..<'不能应用于类型为Int"和Self.IndexDistance"的操作数
错误.
How can I convert the function below to to swift 3
? Currently getting a Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance'
error.
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..
count
returns an IndexDistance
which is the type describing
the distance between two collection indices. IndexDistance
is
required to be a SignedInteger
, but need not be an Int
and can
be different from Index
. Therefore it is not possible to create
the range 0..<count - 1
.
一个解决方案是使用 startIndex
和 endIndex
而不是 0
和 count
:
A solution is to use startIndex
and endIndex
instead of 0
and 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])
}
}
}
}
另一个优点是这也适用于数组 slices(其中第一个元素的索引不一定为零).
Another advantage is that this also works correctly with array slices (where the index of the first element is not necessarily zero).
请注意,根据新的 Swift API 设计指南",shuffle()
是变异 shuffle 方法的正确"名称,和 shuffled()
用于返回数组的非变异对应物:
Note that according to the new "Swift API Design Guidelines",
shuffle()
is the "proper" name for a mutating shuffle method,
and shuffled()
for the non-mutating counterpart which returns an array:
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 中随机排列数组? 同时.
Update: A (even more general) Swift 3 version has been added to How do I shuffle an array in Swift? in the meantime.
对于 Swift 4 (Xcode 9) 必须替换对 swap()
的调用通过调用集合的 swapAt()
方法来实现.也不再需要对 Index
类型的限制:
For Swift 4 (Xcode 9) one has to replace the call to the swap()
function by a call to the swapAt()
method of the collection.
Also the restriction on the Index
type is no longer needed:
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 随机统一,shuffle()
和 shuffled()
是 Swift 标准库的一部分.
As of Swift 4.2 (Xcode 10, currently in beta), with the implementation of
SE-0202 Random Unification,
shuffle()
and shuffled()
are part of the Swift standard library.
这篇关于随机排列数组 swift 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!