生成一个Swift数组,其中包含不重复的随机数。

3
我想在Swift中生成多个不同的随机数。以下是操作步骤。
  1. Set up an empty array
  2. Generate a random number
  3. Check if the array is empty
    a. If the array is empty, insert the random number
    b. If the array is not empty, compare the random number to the numbers in array
    i. If the numbers are the same, repeat 2
    ii. if the numbers are not the same, insert the random number and repeat 2

    import UIKit 
    
    //the random number generator
    func randomInt(min: Int, max:Int) -> Int {
        return min + Int(arc4random_uniform(UInt32(max - min + 1)))
    }
    
    var temp = [Int]()
    for var i = 0; i<4; i++ {
      var randomNumber = randomInt(1, 5)
      if temp.isEmpty{
        temp.append(randomNumber)
      } else {
      //I don't know how to continue...
     }
    }
    

可能是 在 Swift 中从数组获取随机元素 的重复问题。 - Cœur
3个回答

5
如果您使用您的方法,问题在于每次都会创建一个新的随机数。因此,您可能会多次获得相同的随机数,从而导致数组只有一个元素。
因此,如果您只想获取特定范围内(例如0-100)数字的数组,并以随机顺序排列,可以首先用“常规”顺序填充一个数组。例如,使用for循环等:
var min = 1
var max = 5
for var i = min; i<= max; i++ {
    temp.append(i)
}

接下来,您可以使用此答案中的shuffle方法来随机打乱数组的所有元素:

func shuffle<C: MutableCollectionType where C.Index == Int>(var list: C) -> C {
    let count = countElements(list)
    for i in 0..<(count - 1) {
        let j = Int(arc4random_uniform(UInt32(count - i))) + i
        swap(&list[i], &list[j])
    }
    return list
}

之后您可以这样做:
shuffle(temp)        // e.g., [3, 1, 2, 4, 5]

1
你所需要的构造可能类似于以下内容:

您采用的方法可能需要以下构造:

var temp: [Int] = []
while temp.count < 4 {
    var randomNumber: Int
    do {
        randomNumber = randomInt(1, 5)
    } while contains(temp, randomNumber)
    temp.append(randomNumber)
}

这对于像你这样的小范围来说是可以的,但对于更大的范围来说会非常慢,因为对于最后几个数字,你需要等待随机数恰好命中剩余的几个可能性。我刚刚在游乐场里尝试了从200个范围内生成,花了9秒钟。
如果您想要一个保证覆盖范围的随机数选择,您可以像这样取该范围并对其进行洗牌:
func shuffle<S: SequenceType>(source: S) -> [S.Generator.Element] {
    var rangen = GeneratorOf { arc4random() }
    let a = Array(Zip2(rangen, source))
    return a.sorted { $0.0 < $1.0 }.map { $0.1 }
}

let min = 1, max = 5
shuffle(min...max)

如果你想从范围0..<m中选择n个不重复的随机数,那么有一种特别漂亮的算法能够生成这个范围内的升序随机数字序列:
func randomGeneratorOf(#n: Int, #from: Int) -> GeneratorOf<Int> {

    var select = UInt32(n)
    var remaining = UInt32(from)
    var i = 0

    return GeneratorOf {
        while i < from {
            if arc4random_uniform(remaining) < select {
                --select
                --remaining
                return i++
            }
            else {
                --remaining
                ++i
            }
        }
        return nil
    }
}

Which you could use like so:

let engines = [
    "Duck","Emily","Gordon","Henry", "Mavis",
    "Belle","James","Edward","Thomas","Toby"
]

let picks = Array(randomGeneratorOf(n: 3, from: engines.count))

for engine in PermutationGenerator(elements: engines, indices: picks) {
    println(engine)
}

1
以下是我的建议。 我喜欢这种方式,因为它简短而简单 :)
let totalCount: Int = 150 //Any number you asssign
var randomNumArray: [Int] = []
var i = 0
while randomNumArray.count < totalCount {
    i++
    let rand = Int(arc4random_uniform(UInt32(totalCount)))
    for(var ii = 0; ii < totalCount; ii++){
        if randomNumArray.contains(rand){
            print("do nothing")
        } else {
            randomNumArray.append(rand)
        }
    }
}

1
你的变量 (i) 没有被使用。 - Kyle Clegg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接