我有一个字符串数组。我想随机地从这个数组中显示3个独特的项目。然后每5秒,其中一个项目被另一个唯一项目替换(我的想法是添加一个延迟的动画)。
我可以显示3个字符串,但有时它们会重复,而计时器不会更新factLabel标签。
这是我的进步:
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
func randomFact() -> String {
let arrayCount = model.cancunFacts.count
let randomIndex = Int(arc4random_uniform(UInt32(arrayCount)))
return model.cancunFacts[randomIndex]
}
// Display the facts
func updateUI() {
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(randomFact), userInfo: nil, repeats: true)
factLabel.text = randomFact() + " " + randomFact() + " " + randomFact()
}
如何让文字随机更新,而不重复3个事实?
答案 0 :(得分:3)
创建索引数组。从数组中删除一个随机索引,用它来索引你的字符串。当索引数组为空时,重新填充它。
以下是一些生成随机,非重复字符串的示例代码:
var randomStrings = ["Traitor", "Lord Dampnut", "Cheeto-In-Chief",
"F***face Von Clownstick", "Short-Fingered Vulgarian",
"Drumpf", "Der Gropenführer", "Pumpkin in a suit"]
var indexes = [Int]()
func randomString() -> String {
if indexes.isEmpty {
indexes = Array(0...randomStrings.count-1)
}
let index = Int(arc4random_uniform(UInt32(indexes.count)))
let randomIndex = indexes.remove(at: index)
return randomStrings[randomIndex]
}
for i in 1...100 {
print (randomString())
}
(请注意,当索引数组为空且需要重新填充时,它仍然可能会生成重复的字符串。您需要添加额外的逻辑来防止这种情况。)
以下是相同的代码,稍微修改以避免在索引数组为空且需要重新填充时重复:
var randomStrings = ["tiny-fingered", "cheeto-faced", "ferret-wearing", "sh*tgibbon"]
var indexes = [Int]()
var lastIndex: Int?
func randomString() -> String {
if indexes.isEmpty {
indexes = Array(0...randomStrings.count-1)
}
var randomIndex: Int
repeat {
let index = Int(arc4random_uniform(UInt32(indexes.count)))
randomIndex = indexes.remove(at: index)
} while randomIndex == lastIndex
lastIndex = randomIndex
return randomStrings[randomIndex]
}
for i in 1...10000 {
print (randomString())
}
即使它使用了repeat ... while语句,重复条件也不会连续两次触发,因为除了重新填充索引数组之外,你永远不会重复。 / p>
使用该代码,如果存在重复,则在通过该数组时将跳过所选字符串。为了避免这种情况,您需要稍微调整代码,以便在验证数据不是重复之前不从数组中删除给定索引。
上面的版本2,如果在重新填充数组时选择重复,则会跳过一个条目。我写了第三个版本的代码,重新填充数组,删除它返回的最后一项,以便它不能重复,然后在它挑选一个随机项后将其添加回数组。第三个版本将始终返回源数组中的每个项目,然后重新填充它,并且也永远不会重复项目。因此,它是真正随机的,没有偏见:
import UIKit
var randomStrings = ["Traitor", "Lord Dampnut", "Cheeto-In-Chief",
"F***face Von Clownstick", "Short-Fingered Vulgarian",
"Drumpf", "Der Gropenführer", "Pumpkin in a suit"]
var indexes = [Int]()
var lastIndex: Int?
var indexToPutBack: Int?
func randomString() -> String {
//If our array of indexes is empty, fill it.
if indexes.isEmpty {
indexes = Array(0...randomStrings.count-1)
print("") //Print a blank line each time we refill the array so you can see
//If we have returned an item previously, find and remove that index
//From the refilled array
if let lastIndex = lastIndex,
let indexToRemove = indexes.index(of: lastIndex) {
indexes.remove(at: indexToRemove)
indexToPutBack = indexToRemove //Remember the index we removed so we can put it back.
}
}
var randomIndex: Int
let index = Int(arc4random_uniform(UInt32(indexes.count)))
randomIndex = indexes.remove(at: index)
//If we refilled the array and removed an index to avoid repeats, put the removed index back in the array
if indexToPutBack != nil{
indexes.append(indexToPutBack!)
indexToPutBack = nil
}
lastIndex = randomIndex
return randomStrings[randomIndex]
}
for i in 1...30 {
print (randomString())
}
示例输出:
Short-Fingered Vulgarian
F***face Von Clownstick
Pumpkin in a suit
Drumpf
Lord Dampnut
Traitor
Der Gropenführer
Cheeto-In-Chief
Der Gropenführer
Drumpf
Lord Dampnut
Short-Fingered Vulgarian
Cheeto-In-Chief
Pumpkin in a suit
Traitor
F***face Von Clownstick
Short-Fingered Vulgarian
F***face Von Clownstick
Drumpf
Traitor
Cheeto-In-Chief
Lord Dampnut
Pumpkin in a suit
Der Gropenführer
Lord Dampnut
Short-Fingered Vulgarian
Pumpkin in a suit
Cheeto-In-Chief
Der Gropenführer
F***face Von Clownstick
答案 1 :(得分:0)
你的计时器正在调用随机事实,它只是返回一个事实,并没有做任何事情。你可能应该有一个名为initializeTimer的第三个方法来执行Timer.scheduledtimer,你应该从你的updateUI方法中取出它。该计时器应该调用updateUI。这将修复您的标签更新。您还可以在viewDidLoad中调用initializeTimer而不是updateUI。至于防止重复事实,Duncan C的想法就是设置一个单独的数组,当你设置新的随机事实时你从中删除项目,然后在空的时候重新填充它似乎是一个好主意。 / p>
答案 2 :(得分:0)
最简单的方法是维护两个随机字符串数组usedStrings
和unusedStrings
,如下所示:
var unusedStrings: [String] = ["king", "philip", "calls", "out", "for", "good", "soup"]
var usedStrings: [String] = []
func randomString() -> String {
if unusedStrings.isEmpty() {
unusedStrings = usedStrings
usedStrings = []
}
let randomIndex = Int(arc4random_uniform(unusedStrings.count))
let randomString = unusedStrings[randomIndex]
usedStrings.append(randomString)
return randomString
}