随机排列swift 3 [英] Shuffle array swift 3
问题描述
如何将下面的功能转换为swift 3
?当前出现Binary operator '..<' cannot be applied to operands of type 'Int' and '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 - 1
.
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()
是变异随机播放方法的适当"名称,
和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添加swapAt
的更多信息.
See SE-0173 Add MutableCollection.swapAt(_:_:)
for more information about 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屋!