如何将下面的函数转换为swift 3?当前出现Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance'错误。
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]) } } }
count返回,IndexDistance它是描述两个集合索引之间距离的类型。IndexDistance必须为SignedInteger,但不必为Int,可以与有所不同Index。因此,不可能创建范围0..<count - 1。
count
IndexDistance
SignedInteger
Int
Index
0..<count - 1
一个解决方案是使用startIndex和endIndex代替0and count:
startIndex
endIndex
0
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()返回数组的非变异对应方法的“适当”名称:
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中添加了一个(甚至更通用的)Swift 3版本
对于 Swift 4(Xcode 9) ,必须用对集合方法的swap() 调用来代替对函数的调用swapAt()。同样,Index不再需要对类型的限制:
swap()
swapAt()
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-0173MutableCollection.swapAt(_:_:)swapAt。
MutableCollection.swapAt(_:_:)
swapAt
从 Swift 4.2 (Xcode 10,当前处于beta版)开始,具有 SE-0202 Random Unification的实现, shuffle()并且shuffled()是Swift标准库的一部分。