如何将以下功能转换为 <suite name="Factory" group-by-instances="true">
or
<test name="Factory" group-by-instances="true">
?目前收到swift 3
错误。
Binary operator '..<' cannot be applied to operands of type 'Int' and 'Self.IndexDistance'
答案 0 :(得分:78)
count
返回IndexDistance
,这是描述的类型
两个集合索引之间的距离。 IndexDistance
是
必须是SignedInteger
,但无需Int
即可
与Index
不同。因此无法创建
范围0..<count - 1
。
解决方案是使用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 Design Guidelines",
shuffle()
是变异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版本 How do I shuffle an array in 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)
}
}
}
有关swapAt
。
MutableCollection.swapAt(_:_:)
截至 Swift 4.2 (Xcode 10,目前处于测试阶段),随着执行
SE-0202 Random Unification,
shuffle()
和shuffled()
是Swift标准库的一部分。
答案 1 :(得分:10)
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)
答案 2 :(得分:8)
我建议简单地改组数组,而不是试图将它扩展到集合中:
extension Array {
mutating func shuffle () {
for i in (0..<self.count).reversed() {
let ix1 = i
let ix2 = Int(arc4random_uniform(UInt32(i+1)))
(self[ix1], self[ix2]) = (self[ix2], self[ix1])
}
}
}
答案 3 :(得分:0)
您可以使用GameplayKit框架中的NSArray扩展:
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]