简体   繁体   English

如何避免在 Swift 中连续两次生成相同的随机字符串?

[英]How to avoid generating the same random String twice in a row in Swift?

I'm trying to get a random value from an array of strings from an SQLite database, without getting the same value twice in a row (same value should be able to appear again later, but not immediately after).我试图从 SQLite 数据库中的字符串数组中获取随机值,而不是连续两次获得相同的值(相同的值应该能够稍后再次出现,但不会立即出现)。 How can I achieve this in Swift?如何在 Swift 中实现这一点?

It depends on your criteria for when the same value able to appear again这取决于您何时能够再次出现相同值的标准

you can try using the shuffle or shuffled function to shuffle your array and you can get the value from first to last to make it never show the same value您可以尝试使用shuffleshuffled function 来洗牌您的数组,您可以从头到尾获取值,使其永远不会显示相同的值

let x = [1, 2, 3].shuffled()
// x == [2, 3, 1]

var numbers = [1, 2, 3, 4]
numbers.shuffle()
// numbers == [3, 2, 1, 4]

You can create a randomIndex method to return a random index except a previous index that you can store in a var.您可以创建一个 randomIndex 方法来返回一个随机索引,您可以存储在 var 中的先前索引除外。 So the first time you pass nil it will return any index of a collection.因此,第一次传递 nil 时,它将返回集合的任何索引。 If you pass the last random index just remove it from the collection indices, return a new random index and use it to call your method the next time you need a random index:如果您传递最后一个随机索引,只需将其从集合索引中删除,返回一个新的随机索引并在下次需要随机索引时使用它来调用您的方法:

Something like:就像是:

extension RandomAccessCollection where Index == Int {
    func randomIndex(except index: Index? = nil) -> Index? {
        guard let index = index else { return indices.randomElement() }
        var indices = Array(self.indices)
        indices.remove(at: index)
        return indices.randomElement()
    }
}

Usage:用法:

class ViewController: UIViewController {
    let strings = ["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]
    lazy var index = strings.randomIndex()! // this will return any index of the collection to start
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    var randomElement: String {
        // this will get the next random index after returning the random element
        defer { index = strings.randomIndex(except: index)! }
        return strings[index]
    }
}

Playground testing:游乐场测试:

let vc = ViewController()
vc.randomElement  // "Two"
vc.randomElement  // "Three"
vc.randomElement  // "Two"
vc.randomElement  // "Eight"
vc.randomElement  // "Nine"
vc.randomElement  // "Six"
vc.randomElement  // "One"
vc.randomElement  // "Four"
vc.randomElement  // "Six"
vc.randomElement  // "Five"
vc.randomElement  // "Eight"
vc.randomElement  // "Five"
vc.randomElement  // "Four"
vc.randomElement  // "Seven"
vc.randomElement  // "Four"

Since you only care about not repeating the value as the next value, just remember the previous value and reject the next value if it is the same as the previous value.由于您只关心不重复该值作为下一个值,因此只需记住上一个值并拒绝下一个值,如果它与上一个值相同。

Here's a playground example.这是一个游乐场示例。 First, we try this the simplest way:首先,我们尝试这个最简单的方法:

let pep = ["manny", "moe", "jack"]

func fetchRandomPep() -> String {
    return pep.randomElement()!
}

for _ in 1...100 {
    let result = fetchRandomPep()
    print(result)
}

Well, you probably got many repeated results.好吧,你可能得到了很多重复的结果。 Let's prevent that by writing our loop in a different way:让我们以不同的方式编写循环来防止这种情况发生:

var prev = ""
for _ in 1...100 {
    var result = fetchRandomPep()
    while result == prev {
        result = fetchRandomPep()
    }
    prev = result
    print(result)
}

Now there are no repetitions!现在没有重复了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM