从范围内生成 Swift 中的唯一随机数列表
Generate list of unique random numbers in Swift from range
我想写一个函数,它应该 return 整数列表。整数列表大小和最大随机数将由用户定义,用户将通过函数参数传递。我的特殊要求是,integer into list不能冗余
我使用 Array
的方法:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int]{
var randomNumbers = [Int]()
for _ in 1...listSize{
let randomNumber = Int(arc4random_uniform(UInt32(listSize)))
randomNumbers.append(randomNumber)
}
return randomNumbers
}
问题:有时我会用这种方法得到重复的值。
我知道 swift Set
不包含重复值。
我使用 Set
的方法:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> Set<Int>{
var randomNumbers = Set<Int>()
for _ in 1...listSize{
let randomNumber = Int(arc4random_uniform(UInt32(listSize)))
randomNumbers.insert(randomNumber)
}
return randomNumbers
}
问题:有时 Set
大小小于用户定义的大小。
你只需要使用 while count is less than listSize 而不是 for 循环,而不是你需要将 maxNumber 加一而不是 listSize 传递给 arc4random_uniform:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> Set<Int> {
var randomNumbers = Set<Int>()
while randomNumbers.count < listSize {
let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1)))
randomNumbers.insert(randomNumber)
}
return randomNumbers
}
getRandomNumbers(maxNumber: 10, listSize: 3) // {5, 7, 0}
当您获得重复的随机数时会发生这种情况。您可以检查 randomNumbers.count 并生成随机数,直到达到 listSize.
,而不是生成 listSize 随机数
这里有2个问题:
您没有生成足够的数字。您需要不断生成随机数,直到您的集合足够大:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int] {
var randomNumbers = Set<Int>()
while randomNumbers.count < listSize {
let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1)))
randomNumbers.insert(randomNumber)
}
return randomNumbers
}
您通过将随机数置于 Set 选择的顺序中来使它们产生偏差,这是高度可预测的。您应该将您的数字附加到一个数组(以保持它们的顺序生成它们),同时仍然并行地利用一个集合,以实现快速重复数据删除:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int] {
precondition(listSize < maxNumber, "Cannot generate a list of \(listSize) unique numbers, if they all have to be less than \(maxNumber)")
var randomNumbers = (array: [Int](), set: Set<Int>())
while randomNumbers.set.count < listSize {
let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1)))
if randomNumbers.set.insert(randomNumber).inserted { // If the number is unique
randomNumbers.array.append(randomNumber) // then also add it to the arary
}
}
return randomNumbers.array
}
还有另一种可能性。我不认为这是最好的,但在我看来 IndexSet
可能是解决问题的好方法(基本上,这个想法 nerd-sniped 我和我必须找到答案),这就是我想出的。
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int]{
guard maxNumber < listSize else { return [] }
var indexSet = IndexSet(integersIn: 0...listSize)
var randomInts = [Int]()
while randomInts.count < maxNumber {
guard let currentInt = indexSet.integerLessThanOrEqualTo(Int(arc4random_uniform(UInt32(listSize)))) else {
continue
}
randomInts.append(currentInt)
indexSet.remove(currentInt)
}
return randomInts
}
想法是创建一个 IndexSet
覆盖 0 到请求的最大值,然后从该集合中随机删除元素,直到你有足够的元素。它通过在使用时从集合中删除整数来避免重复。 IndexSet
实际上不是 Set
,它是存储一堆唯一整数的有效方式,因此它获得了 Set
的唯一性,而无需实际创建包含所有内容的 Set
范围内的整数。
Swift 5 版本实现
extension Int {
static func getUniqueRandomNumbers(min: Int, max: Int, count: Int) -> [Int] {
var set = Set<Int>()
while set.count < count {
set.insert(Int.random(in: min...max))
}
return Array(set)
}
}
例如:
let uniqueNumbers = Int.getUniqueRandomNumbers(min: 1000, max: 1500, count: 10)
示例结果:
[1454, 1105, 1305, 1176, 1498, 1127, 1310, 1209, 1373, 1198]
我想写一个函数,它应该 return 整数列表。整数列表大小和最大随机数将由用户定义,用户将通过函数参数传递。我的特殊要求是,integer into list不能冗余
我使用 Array
的方法:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int]{
var randomNumbers = [Int]()
for _ in 1...listSize{
let randomNumber = Int(arc4random_uniform(UInt32(listSize)))
randomNumbers.append(randomNumber)
}
return randomNumbers
}
问题:有时我会用这种方法得到重复的值。
我知道 swift Set
不包含重复值。
我使用 Set
的方法:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> Set<Int>{
var randomNumbers = Set<Int>()
for _ in 1...listSize{
let randomNumber = Int(arc4random_uniform(UInt32(listSize)))
randomNumbers.insert(randomNumber)
}
return randomNumbers
}
问题:有时 Set
大小小于用户定义的大小。
你只需要使用 while count is less than listSize 而不是 for 循环,而不是你需要将 maxNumber 加一而不是 listSize 传递给 arc4random_uniform:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> Set<Int> {
var randomNumbers = Set<Int>()
while randomNumbers.count < listSize {
let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1)))
randomNumbers.insert(randomNumber)
}
return randomNumbers
}
getRandomNumbers(maxNumber: 10, listSize: 3) // {5, 7, 0}
当您获得重复的随机数时会发生这种情况。您可以检查 randomNumbers.count 并生成随机数,直到达到 listSize.
,而不是生成 listSize 随机数这里有2个问题:
您没有生成足够的数字。您需要不断生成随机数,直到您的集合足够大:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int] { var randomNumbers = Set<Int>() while randomNumbers.count < listSize { let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1))) randomNumbers.insert(randomNumber) } return randomNumbers }
您通过将随机数置于 Set 选择的顺序中来使它们产生偏差,这是高度可预测的。您应该将您的数字附加到一个数组(以保持它们的顺序生成它们),同时仍然并行地利用一个集合,以实现快速重复数据删除:
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int] { precondition(listSize < maxNumber, "Cannot generate a list of \(listSize) unique numbers, if they all have to be less than \(maxNumber)") var randomNumbers = (array: [Int](), set: Set<Int>()) while randomNumbers.set.count < listSize { let randomNumber = Int(arc4random_uniform(UInt32(maxNumber+1))) if randomNumbers.set.insert(randomNumber).inserted { // If the number is unique randomNumbers.array.append(randomNumber) // then also add it to the arary } } return randomNumbers.array }
还有另一种可能性。我不认为这是最好的,但在我看来 IndexSet
可能是解决问题的好方法(基本上,这个想法 nerd-sniped 我和我必须找到答案),这就是我想出的。
func getRandomNumbers(maxNumber: Int, listSize: Int)-> [Int]{
guard maxNumber < listSize else { return [] }
var indexSet = IndexSet(integersIn: 0...listSize)
var randomInts = [Int]()
while randomInts.count < maxNumber {
guard let currentInt = indexSet.integerLessThanOrEqualTo(Int(arc4random_uniform(UInt32(listSize)))) else {
continue
}
randomInts.append(currentInt)
indexSet.remove(currentInt)
}
return randomInts
}
想法是创建一个 IndexSet
覆盖 0 到请求的最大值,然后从该集合中随机删除元素,直到你有足够的元素。它通过在使用时从集合中删除整数来避免重复。 IndexSet
实际上不是 Set
,它是存储一堆唯一整数的有效方式,因此它获得了 Set
的唯一性,而无需实际创建包含所有内容的 Set
范围内的整数。
Swift 5 版本实现
extension Int {
static func getUniqueRandomNumbers(min: Int, max: Int, count: Int) -> [Int] {
var set = Set<Int>()
while set.count < count {
set.insert(Int.random(in: min...max))
}
return Array(set)
}
}
例如:
let uniqueNumbers = Int.getUniqueRandomNumbers(min: 1000, max: 1500, count: 10)
示例结果:
[1454, 1105, 1305, 1176, 1498, 1127, 1310, 1209, 1373, 1198]