Reputation:
I read in https://www.hackingwithswift.com/read/35/2/generating-random-numbers-in-ios-8-and-earlier that the best way to generate a random number is to use
let r = arc4random_uniform(UInt32(_names.count))
let name : String = _names[Int(r)]
but it seems odd that I have to cast twice to be able to get a random number, what should I do to avoid casting?
Upvotes: 7
Views: 6661
Reputation: 120210
You can initial a random element:
let randomInt = Int.random(in: 0...1)
let randomDouble = Double.random(in: 0...1)
Also You can take a random element from a collection like
let randomInt = (0...9).randomElement()
Also there is another handy method that you can use on array for shuffling that you may need:
let shuffled = [1, 2, 3, 4].shuffled()
Upvotes: 2
Reputation: 176
Modified answer from Luca written as extension in Swift 4
/// Returns random number within given range, upper bound included, eg. -1...0 = [-1, 0, 1]
extension CountableClosedRange where Bound == Int
{
var random: Int
{
let range = self
let offset: Int = range.lowerBound < 0 ? abs(range.lowerBound) : 0
let min = UInt32(range.lowerBound + offset)
let max = UInt32(range.upperBound + offset)
let randomNumber = Int(min + arc4random_uniform(max - min + 1)) - offset
return randomNumber
}
}
/// Returns random number within given range, upper bound not included, eg. -1...0 = [-1, 0]
extension CountableRange where Bound == Int
{
var random: Int
{
let range = self
let offset: Int = range.lowerBound < 0 ? abs(range.lowerBound) : 0
let min = UInt32(range.lowerBound + offset)
let max = UInt32(range.upperBound + offset)
let randomNumber = Int(min + arc4random_uniform(max - min)) - offset
return randomNumber
}
}
Examples:
(0...10).random
(0..<10).random
Upvotes: 1
Reputation: 59536
I really like using this extension
extension Int {
init(random range: Range<Int>) {
let offset: Int
if range.startIndex < 0 {
offset = abs(range.startIndex)
} else {
offset = 0
}
let min = UInt32(range.startIndex + offset)
let max = UInt32(range.endIndex + offset)
self = Int(min + arc4random_uniform(max - min)) - offset
}
}
Now you can generate a random Int
indicating the range
let a = Int(random: 1...10) // 3
let b = Int(random: 0..<10) // 6
let c = Int(random: 0...100) // 31
let d = Int(random: -10...3) // -4
Upvotes: 3
Reputation: 9411
It really depends on how much casting you want to avoid. You could simply wrap it in a function:
func random(max maxNumber: Int) -> Int {
return Int(arc4random_uniform(UInt32(maxNumber)))
}
So then you only have to do the ugly casting once. Everywhere you want a random number with a maximum number:
let r = random(max: _names.count)
let name: String = _names[r]
As a side note, since this is Swift, your properties don't need _
in front of them.
Upvotes: 7
Reputation: 42129
Or you could use
let name : String = _names[ Int(arc4random()) % _names.count ]
Upvotes: 0
Reputation: 1589
you can use gameplaykit
let random = GKRandomDistribution(lowestValue: 0, highestValue: 100)
let r = random.nextInt()
Upvotes: 1