【问题标题】:Get a random unique element from an Array until all elements have been picked in Swift从 Array 中获取随机唯一元素,直到在 Swift 中选择了所有元素
【发布时间】:2019-02-21 13:02:39
【问题描述】:

我有以下数组:

var notebookCovers = ["cover1", "cover2", "cover3", "cover4", "cover4", "cover6", "cover7", "cover8", "cover9", "cover10"]

还有一个UIButton,当它被按下时,它会生成一个带有数组元素之一的新UIImage

我需要做的是每次点击按钮以从数组中生成随机但唯一的元素(不重复元素),直到它们全部被选中,然后再次重新启动数组。

到目前为止,我得到了一个随机元素,但它是重复的,我不知道怎么做,所以它每次都会得到一个独特的图像

func createNewNotebook() {
    let newNotebook = Notebook()
    let randomInt = randomNumber()
    newNotebook.coverImageString = notebookCovers[randomInt]
    notebooks.insert(newNotebook, at: 0)
    collectionView.reloadData()
}

func randomNumber() -> Int {
    var previousNumber = arc4random_uniform(UInt32(notebookCovers.count))   
    var randomNumber = arc4random_uniform(UInt32(notebookCovers.count - 1)) 
    notebookCovers.shuffle()
    if randomNumber == previousNumber {
        randomNumber = UInt32(notebookCovers.count - 1)
    }
    previousNumber = randomNumber
    return Int(randomNumber)
}

【问题讨论】:

  • 你不能只复制数组并删除元素直到不再剩下吗?
  • 复制数组。随机播放副本。现在只需继续删除第一个元素,直到副本为空。当它为空时,重新开始。
  • @matt 我实际上实现了你的方法。这容易多了!谢谢!
  • 把它作为答案。

标签: ios arrays swift


【解决方案1】:

Set 是一个包含唯一元素的集合类型。将您的 notebooks 数组转换为 Set 还可以让您利用其 randomElement 函数

var aSet = Set(notebooks)

let element = aSet.randomElement()
aSet.remove(element)

【讨论】:

    【解决方案2】:

    复制数组。随机播放副本。现在只需继续删除第一个元素,直到副本为空。当它为空时,重新开始。

    例子:

    let arr = [1,2,3,4,5]
    var copy = [Int]()
    for _ in 1...30 { // just to demonstrate what happens
        if copy.isEmpty { copy = arr; copy.shuffle() }
        let element = copy.removeFirst() ; print(element, terminator:" ")
    }
    // 4 2 3 5 1 1 5 3 2 4 4 1 2 3 5 1 4 5 2 3 3 5 4 2 1 3 2 4 5 1
    

    【讨论】:

    • 完成!谢谢!
    【解决方案3】:

    如果要创建循环解决方案:

    let originalSet = Set(arrayLiteral: "a","b","c")
    var selectableSet = originalSet
    
    func repeatingRandomObject() -> String {
        if selectableSet.isEmpty {
            selectableSet = originalSet
        }
    
        return selectableSet.remove(selectableSet.randomElement()!)!
    }
    

    强制解包在这里是安全的,因为我们知道结果永远不会为零。如果您不想强制展开:

    let originalSet = Set(arrayLiteral: "a","b","c")
    var selectableSet = originalSet
    
    func repeatingRandomObject() -> String? {
        if selectableSet.isEmpty {
            selectableSet = originalSet
        }
    
        guard let randomElement = selectableSet.randomElement() else { return nil }
        return selectableSet.remove(randomElement)
    }
    

    【讨论】:

      【解决方案4】:

      你可以试试这样的,

      var notebookCovers = ["cover1", "cover2", "cover3", "cover4", "cover4", "cover6", "cover7", "cover8", "cover9", "cover10"]
      var tappedNotebooks: [String] = []
      func tapping() {
          let notebook  =  notebookCovers[Int.random(in: 0...notebookCovers.count - 1)]
          if tappedNotebooks.contains(notebook){
              print("already exists trying again!")
              tapping()
          } else {
              tappedNotebooks.append(notebook)
              print("appended", notebook)
          }
          if tappedNotebooks == notebookCovers {
              tappedNotebooks = []
              print("cleared Tapped notebooks")
          }
      }
      

      【讨论】:

        【解决方案5】:

        随机播放是可能的:

        struct AnantShuffler<Base: MutableCollection> {
        
            private var collection: Base
            private var index: Base.Index
        
            public init?(collection: Base) {
                guard !collection.isEmpty else {
                    return nil
                }
                self.collection = collection
                self.index = collection.startIndex
            }
        
            public mutating func next() -> Base.Iterator.Element {
                let result = collection[index]
                collection.formIndex(after: &index)
                if index == collection.endIndex {
                    collection.shuffle()
                    index = collection.startIndex
                }
                return result
            }
        }
        
        fileprivate extension MutableCollection {
            /// Shuffles the contents of this collection.
            mutating func shuffle() {
                let c = count
                guard c > 1 else { return }
        
                for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
                    let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
                    let i = index(firstUnshuffled, offsetBy: d)
                    swapAt(firstUnshuffled, i)
                }
            }
        }
        

        用途:

        let shuffler = AnantShuffler(collection: ["c1","c2","c3"].shuffled())
        shuffler?.next()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-31
          • 2012-09-09
          • 2014-06-19
          • 1970-01-01
          • 2013-04-21
          相关资源
          最近更新 更多