从数组中选取一个随机元素

假设我有一个数组,我想随机select一个元素。

什么是最简单的方法来做到这一点?

显而易见的方法是array[random index] 。 但也许有一些像ruby的array.sample ? 或者,如果不能通过使用扩展名创build这样的方法?

只要回答你的问题,你可以做到这一点,以实现随机数组select:

 let array = ["Frodo", "sam", "wise", "gamgee"] let randomIndex = Int(arc4random_uniform(UInt32(array.count))) print(array[randomIndex]) 

铸件是丑陋的,但我相信他们是必需的,除非别人有另一种方式。

关于Lucas说的话,你可以像这样创build一个Array类的扩展:

 extension Array { func randomItem() -> Element? { if isEmpty { return nil } let index = Int(arc4random_uniform(UInt32(self.count))) return self[index] } } 

例如:

 let myArray = [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16] let myItem = myArray.randomItem() // Note: myItem is an Optional<Int> 

Swift 2.2中,这可以被泛化,所以我们有:

 UInt.random UInt8.random UInt16.random UInt32.random UInt64.random UIntMax.random // closed intervals: (-3...3).random (Int.min...Int.max).random // and collections, which return optionals since they can be empty: (1..<4).sample [1,2,3].sample "abc".characters.sample ["a": 1, "b": 2, "c": 3].sample 

首先,为UnsignedIntegerType实现静态random属性:

 import Darwin func sizeof <T> (_: () -> T) -> Int { // sizeof return type without calling return sizeof(T.self) } let ARC4Foot: Int = sizeof(arc4random) extension UnsignedIntegerType { static var max: Self { // sadly `max` is not required by the protocol return ~0 } static var random: Self { let foot = sizeof(Self) guard foot > ARC4Foot else { return numericCast(arc4random() & numericCast(max)) } var r = UIntMax(arc4random()) for i in 1..<(foot / ARC4Foot) { r |= UIntMax(arc4random()) << UIntMax(8 * ARC4Foot * i) } return numericCast(r) } } 

然后,对于具有UnsignedIntegerType边界的ClosedInterval

 extension ClosedInterval where Bound : UnsignedIntegerType { var random: Bound { guard start > 0 || end < Bound.max else { return Bound.random } return start + (Bound.random % (end - start + 1)) } } 

然后(稍微牵扯一点),对于带有SignedIntegerType边界的ClosedInterval (使用下面进一步描述的帮助器方法):

 extension ClosedInterval where Bound : SignedIntegerType { var random: Bound { let foot = sizeof(Bound) let distance = start.unsignedDistanceTo(end) guard foot > 4 else { // optimisation: use UInt32.random if sufficient let off: UInt32 if distance < numericCast(UInt32.max) { off = UInt32.random % numericCast(distance + 1) } else { off = UInt32.random } return numericCast(start.toIntMax() + numericCast(off)) } guard distance < UIntMax.max else { return numericCast(IntMax(bitPattern: UIntMax.random)) } let off = UIntMax.random % (distance + 1) let x = (off + start.unsignedDistanceFromMin).plusMinIntMax return numericCast(x) } } 

…其中unsignedDistanceTounsignedDistanceFromMinplusMinIntMax帮助器方法可以实现如下:

 extension SignedIntegerType { func unsignedDistanceTo(other: Self) -> UIntMax { let _self = self.toIntMax() let other = other.toIntMax() let (start, end) = _self < other ? (_self, other) : (other, _self) if start == IntMax.min && end == IntMax.max { return UIntMax.max } if start < 0 && end >= 0 { let s = start == IntMax.min ? UIntMax(Int.max) + 1 : UIntMax(-start) return s + UIntMax(end) } return UIntMax(end - start) } var unsignedDistanceFromMin: UIntMax { return IntMax.min.unsignedDistanceTo(self.toIntMax()) } } extension UIntMax { var plusMinIntMax: IntMax { if self > UIntMax(IntMax.max) { return IntMax(self - UIntMax(IntMax.max) - 1) } else { return IntMax.min + IntMax(self) } } } 

最后,对于Index.Distance == Int所有集合:

 extension CollectionType where Index.Distance == Int { var sample: Generator.Element? { if isEmpty { return nil } let end = UInt(count) - 1 let add = (0...end).random let idx = startIndex.advancedBy(Int(add)) return self[idx] } } 

…可以对整数Range稍微优化Range s:

 extension Range where Element : SignedIntegerType { var sample: Element? { guard startIndex < endIndex else { return nil } let i: ClosedInterval = startIndex...endIndex.predecessor() return i.random } } extension Range where Element : UnsignedIntegerType { var sample: Element? { guard startIndex < endIndex else { return nil } let i: ClosedInterval = startIndex...endIndex.predecessor() return i.random } } 

你也可以使用Swift内置的random()函数来扩展:

 extension Array { func sample() -> Element { let randomIndex = Int(rand()) % count return self[randomIndex] } } let array = [1, 2, 3, 4] array.sample() // 2 array.sample() // 2 array.sample() // 3 array.sample() // 3 array.sample() // 1 array.sample() // 1 array.sample() // 3 array.sample() // 1 

Swift 3版本:

 extension Collection where Index == Int { /** Picks a random element of the collection. - returns: A random element of the collection. */ func randomElement() -> Iterator.Element? { return isEmpty ? nil : self[Int(arc4random_uniform(UInt32(endIndex)))] } } 

另一个Swift 3的build议

 private extension Array { var randomElement: Element { let index = Int(arc4random_uniform(UInt32(count))) return self[index] } } 

以下别人回答,但用Swift 2的支持。

Swift 1.x

 extension Array { func sample() -> T { let index = Int(arc4random_uniform(UInt32(self.count))) return self[index] } } 

Swift 2.x

 extension Array { func sample() -> Element { let index = Int(arc4random_uniform(UInt32(self.count))) return self[index] } } 

例如:

 let arr = [2, 3, 5, 7, 9, 11, 13, 17, 19, 23, 29, 31] let randomSample = arr.sample() 

检查空数组的替代function实现。

 func randomArrayItem<T>(array: [T]) -> T? { if array.isEmpty { return nil } let randomIndex = Int(arc4random_uniform(UInt32(array.count))) return array[randomIndex] } randomArrayItem([1,2,3]) 

这是数组的一个扩展,用一个空数组检查更安全:

 extension Array { func sample() -> Element? { if self.isEmpty { return nil } let randomInt = Int(arc4random_uniform(UInt32(self.count))) return self[randomInt] } } 

你可以像这样简单地使用它:

 let digits = Array(0...9) digits.sample() // => 6 

如果你更喜欢一个框架 ,也有一些更方便的function,然后检查HandySwift 。 您可以通过Carthage将其添加到您的项目中然后像上面的示例一样使用它:

 import HandySwift let digits = Array(0...9) digits.sample() // => 8 

此外,它还包括一次获得多个随机元素的选项:

 digits.sample(size: 3) // => [8, 0, 7] 

Swift 3

导入GameKit

 func getRandomMessage() -> String { let messages = ["one", "two", "three"] let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: messages.count) return messages[randomNumber].description } 

Swift 3 – 简单易用。

  1. 创build数组

     var arrayOfColors = [UIColor.red, UIColor.yellow, UIColor.orange, UIColor.green] 
  2. 创build随机颜色

     let randomColor = arc4random() % UInt32(arrayOfColors.count) 
  3. 将该颜色设置为您的对象

     your item = arrayOfColors[Int(randomColor)] 

下面是一个SpriteKit项目用一个随机String更新SKLabelNode的例子:

  let array = ["one","two","three","four","five"] let randomNumber = arc4random() % UInt32(array.count) let labelNode = SKLabelNode(text: array[Int(randomNumber)]) 

我发现使用GameKit的GKRandomSource.sharedRandom()最适合我。

 import GameKit let array = ["random1", "random2", "random3"] func getRandomIndex() -> Int { let randomNumber = GKRandomSource.sharedRandom().nextIntWithUpperBound(array.count) return randomNumber 

或者你可以在select的随机索引处返回对象。 确保函数首先返回一个string,然后返回数组的索引。

  return array[randomNumber] 

简短和重点。

最新的swift3代码尝试它的工作正常

  let imagesArray = ["image1.png","image2.png","image3.png","image4.png"] var randomNum: UInt32 = 0 randomNum = arc4random_uniform(UInt32(imagesArray.count)) wheelBackgroundImageView.image = UIImage(named: imagesArray[Int(randomNum)])