Arrays 生成包含范围内唯一随机数的数组

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

我正在尝试用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: 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)