Arrays 生成包含范围内唯一随机数的数组
我正在尝试用Apple Swift(iOS)编写一个函数,该函数将生成给定数量的唯一随机数,这些随机数在给定的包含范围内,比如0到10之间。所以如果我说我想要5个在0和10之间的唯一随机数,它将返回一个带有[7,10,2,3,0]或[7,10,2,8,0]的数组,以此类推 我的这部分工作是:Arrays 生成包含范围内唯一随机数的数组,arrays,swift,random,swift2,Arrays,Swift,Random,Swift2,我正在尝试用Apple Swift(iOS)编写一个函数,该函数将生成给定数量的唯一随机数,这些随机数在给定的包含范围内,比如0到10之间。所以如果我说我想要5个在0和10之间的唯一随机数,它将返回一个带有[7,10,2,3,0]或[7,10,2,8,0]的数组,以此类推 我的这部分工作是: // Returns an array of unique numbers func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: UIn
// Returns an array of unique numbers
func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: UInt32) -> [Int] {
var uniqueNumbers = [Int]()
while uniqueNumbers.count < numberOfRandoms {
let randomNumber = Int(arc4random_uniform(maxNum + 1)) + minNum
var found = false
for var index = 0; index < uniqueNumbers.count; ++index {
if uniqueNumbers[index] == randomNumber {
found = true
break
}
}
if found == false {
uniqueNumbers.append(randomNumber)
}
}
return uniqueNumbers
}
print(uniqueRandoms(5, minNum: 0, maxNum: 10))
//返回唯一数字的数组
func uniqueRandoms(numberOfRandoms:Int,minNum:Int,maxNum:UInt32)->[Int]{
var uniqueNumbers=[Int]()
而uniqueNumbers.count
现在,我想添加一个功能,在我不想要的范围内将单个数字列入黑名单。假设我仍然想要5个介于0和10之间的唯一随机数,但我不希望它包含8
这部分会导致一个无休止的循环(25%以上的时间或更多),我不明白为什么?以下是我所拥有的:
var blackListNum = 8
// Returns an array of unique numbers
func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: UInt32, checkBlackList: Bool = false) -> [Int] {
var uniqueNumbers = [Int]()
while uniqueNumbers.count < numberOfRandoms {
let randomNumber = Int(arc4random_uniform(maxNum + 1)) + minNum
var found = false
for var index = 0; index < uniqueNumbers.count; ++index {
if checkBlackList == false {
if uniqueNumbers[index] == randomNumber {
found = true
break
}
} else {
if uniqueNumbers[index] == randomNumber || uniqueNumbers[index] == blackListNum {
found = true
break
}
}
}
if found == false {
uniqueNumbers.append(randomNumber)
}
}
return uniqueNumbers
}
print(uniqueRandoms(5, minNum: 0, maxNum: 10, checkBlackList: true))
var blackListNum=8
//返回唯一数字的数组
func uniqueRandoms(numberOfRandoms:Int,minNum:Int,maxNum:UInt32,检查黑名单:Bool=false)->[Int]{
var uniqueNumbers=[Int]()
而uniqueNumbers.count
我知道我的功能远远没有效率,因为我刚刚开始学习Swift,但我想保持它的相似性,因为我想了解它是如何工作的。我不想简单地复制和粘贴其他人更有效的解决方案而不理解它。我刚刚学习了变量、常量、if、while、for等语句和其他基本知识,并希望保持不变。您可以使用一个集合来存储所有随机数,直到达到预期的随机数:
func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: UInt32) -> [Int] {
var uniqueNumbers = Set<Int>()
while uniqueNumbers.count < numberOfRandoms {
uniqueNumbers.insert(Int(arc4random_uniform(maxNum + 1)) + minNum)
}
return uniqueNumbers.shuffled()
}
print(uniqueRandoms(numberOfRandoms: 5, minNum: 0, maxNum: 10))
func uniqueRandoms(numberOfRandoms: Int, minNum: Int, maxNum: UInt32, blackList: Int?) -> [Int] {
var uniqueNumbers = Set<Int>()
while uniqueNumbers.count < numberOfRandoms {
uniqueNumbers.insert(Int(arc4random_uniform(maxNum + 1)) + minNum)
}
if let blackList = blackList {
if uniqueNumbers.contains(blackList) {
while uniqueNumbers.count < numberOfRandoms+1 {
uniqueNumbers.insert(Int(arc4random_uniform(maxNum + 1)) + minNum)
}
uniqueNumbers.remove(blackList)
}
}
return uniqueNumbers.shuffled()
}
uniqueRandoms(numberOfRandoms: 3, minNum: 0, maxNum: 10, blackList: 8) // [0, 10, 7]
func uniqueRandoms(numberOfRandoms:Int,minNum:Int,maxNum:UInt32)->[Int]{
var uniqueNumbers=Set()
而uniqueNumbers.count[Int]{
var uniqueNumbers=Set()
而uniqueNumbers.count
一种直接的方法是创建一个可供选择的数字数组,然后在选择时删除这些数字:
// create an array of 0 through 10
var nums = Array(0...10)
// remove the blacklist number
nums.removeAtIndex(nums.indexOf(8)!)
var randoms = [Int]()
for _ in 1...5 {
let index = Int(arc4random_uniform(UInt32(nums.count)))
randoms.append(nums[index])
nums.removeAtIndex(index)
}
这种方法的优点是,只需在数组中生成所需数量的随机数。由于您是从每次仍然可用的数字中进行选择,因此不必检查是否已经有随机值。以下是我的解决方案:
操作时留下的操作练习。简单的方法是:
let UniqueIdNumber = CFUUIDCreateString(nil, CFUUIDCreate(nil))
Swift 4.0中的解决方案和性能细分
我最近发现自己需要一个解决这个问题的方法,但是没有黑名单,我在这一页上看到了答案,也在上一页看到了答案,但是当选择的数字集非常大,而且选择了很多数字时,我担心性能(比如,你选择了总人数的50%以上)
所以我尝试了一些解决方案
第一种是随机选择一个数字,检查之前是否已经选择了该数字,然后选择一个不同的数字或将其添加到数字列表中
func randomNumber(between lower: Int, and upper: Int) -> Int {
return Int(arc4random_uniform(UInt32(upper - lower))) + lower
}
func generateRandomUniqueNumbers1(forLowerBound lower: Int, andUpperBound upper:Int, andNumNumbers iterations: Int) -> [Int] {
guard iterations <= (upper - lower) else { return [] }
var numbers: [Int] = []
(0..<iterations).forEach { _ in
var nextNumber: Int
repeat {
nextNumber = randomNumber(between: lower, and: upper)
} while numbers.contains(nextNumber)
numbers.append(nextNumber)
}
return numbers
}
解决方案2
解决方案3
比较
结论
正如我在第一个解决方案中所怀疑的,它确实陷入了大量人口和高密度的困境。当你没有那么多人口或只选择2个数字时,它仍然非常快,但在这些条件下,所有的解决方案都非常快。即使解决方案1可以选择25个随机数字从250个种群中获得的BER比解决方案2或3快,实时差异非常小
但是,需要指出的是,如果您想要从一个非常大的群体中获得很少的唯一数(即:从12500个群体中获得2个唯一数),那么解决方案1是最快的,大约比解决方案3快77%,两者都比解决方案2快几个数量级。对于我的具体情况,这更接近于我将要讨论的问题
let UniqueIdNumber = CFUUIDCreateString(nil, CFUUIDCreate(nil))
func randomNumber(between lower: Int, and upper: Int) -> Int {
return Int(arc4random_uniform(UInt32(upper - lower))) + lower
}
func generateRandomUniqueNumbers1(forLowerBound lower: Int, andUpperBound upper:Int, andNumNumbers iterations: Int) -> [Int] {
guard iterations <= (upper - lower) else { return [] }
var numbers: [Int] = []
(0..<iterations).forEach { _ in
var nextNumber: Int
repeat {
nextNumber = randomNumber(between: lower, and: upper)
} while numbers.contains(nextNumber)
numbers.append(nextNumber)
}
return numbers
}
func generateRandomUniqueNumbers2(forLowerBound lower: Int, andUpperBound upper:Int, andNumNumbers iterations: Int) -> [Int] {
guard iterations <= (upper - lower) else { return [] }
var indices: [Int] = (lower..<upper).sorted()
var numbers: [Int] = []
(0..<iterations).forEach { _ in
let nextNumberIndex = randomNumber(between: 0, and: indices.count)
let nextNumber: Int = indices[nextNumberIndex]
indices.remove(at: nextNumberIndex)
numbers.append(nextNumber)
}
return numbers
}
func generateRandomUniqueNumbers3(forLowerBound lower: Int, andUpperBound upper:Int, andNumNumbers iterations: Int) -> [Int] {
guard iterations <= (upper - lower) else { return [] }
var numbers: Set<Int> = Set<Int>()
(0..<iterations).forEach { _ in
let beforeCount = numbers.count
repeat {
numbers.insert(randomNumber(between: lower, and: upper))
} while numbers.count == beforeCount
}
return numbers.map{ $0 }
}
(Population: 5; Density: 10%; Iterations: 2,500): 0.0056s
(Population: 250; Density: 10%; Iterations: 50) : 0.0046s
(Population: 12,500; Density: 10%; Iterations: 10) : 1.33s
(Population: 5; Density: 50%; Iterations: 2,500): 0.0131s
(Population: 250; Density: 50%; Iterations: 50) : 0.0912s
(Population: 12,500; Density: 50%; Iterations: 1) : 4.09s
(Population: 5; Density: 90%; Iterations: 2,500): 0.0309s
(Population: 250; Density: 90%; Iterations: 10) : 0.0993s
(Population: 12,500; Density: 90%; Iterations: 1) : 23s
(Population: 5; Density: 10%; Iterations: 2,500): 0.0184s
(Population: 250; Density: 10%; Iterations: 50) : 0.0086s
(Population: 12,500; Density: 10%; Iterations: 10) : 0.103s
(Population: 5; Density: 50%; Iterations: 2,500): 0.0233s
(Population: 250; Density: 50%; Iterations: 50) : 0.0125s
(Population: 12,500; Density: 50%; Iterations: 1) : 0.0209s
(Population: 5; Density: 90%; Iterations: 2,500): 0.0242s
(Population: 250; Density: 90%; Iterations: 10) : 0.0046s
(Population: 12,500; Density: 90%; Iterations: 1) : 0.0278s
(Population: 5; Density: 10%; Iterations: 2,500): 0.00672s
(Population: 250; Density: 10%; Iterations: 50) : 0.0024s
(Population: 12,500; Density: 10%; Iterations: 10) : 0.0148s
(Population: 5; Density: 50%; Iterations: 2,500): 0.0134s
(Population: 250; Density: 50%; Iterations: 50) : 0.00769s
(Population: 12,500; Density: 50%; Iterations: 1) : 0.00789s
(Population: 5; Density: 90%; Iterations: 2,500): 0.0209s
(Population: 250; Density: 90%; Iterations: 10) : 0.00397s
(Population: 12,500; Density: 90%; Iterations: 1) : 0.0163s
(Case 1): Solution 1 is fastest; then 3; then 2
(Case 2): Solution 3 is fastest; then 1; then 2
(Case 3): Solution 3 is fastest; then 2; then 3
(Case 4): Solution 1 is fastest; then 3; then 2
(Case 5): Solution 3 is fastest; then 2; then 1
(Case 6): Solution 3 is fastest; then 2; then 1
(Case 7): Solution 3 is fastest; then 2; then 1
(Case 8): Solution 3 is fastest; then 2; then 1
(Case 9): Solution 3 is fastest; then 2; then 1
// 1st version where I only blacklisted 8
var randomNumbers = [Int]()
for _ in 1...7 {
var number = Int(arc4random_uniform(8))+1
while randomNumbers.contains(number) || number == 8{
number = Int(arc4random_uniform(8))+1
}
randomNumbers.append(number)
}
print(randomNumbers)
// 2nd version where I created an array of blacklisted numbers
var randomNumbers = [Int]()
var blackList = [8, 5, 2, 7]
for _ in 1...3 {
var number = Int(arc4random_uniform(10))+1
while randomNumbers.contains(number) || blackList.contains(number){
number = Int(arc4random_uniform(10))+1
}
randomNumbers.append(number)
}
print(randomNumbers)