How to get random element from a set in Swift?

前端 未结 6 969
别那么骄傲
别那么骄傲 2021-01-04 06:41

As of Swift 1.2, Apple introduces Set collection type.

Say, I have a set like:

var set = Set(arrayLiteral: 1, 2, 3, 4, 5)


        
相关标签:
6条回答
  • 2021-01-04 06:47
    extension Set {
        func randomElement() -> Element? {
            return count == 0 ? nil : self[advance(self.startIndex, Int(arc4random()) % count)]
        }
    }
    
    0 讨论(0)
  • 2021-01-04 06:51

    If you want a 'random' element from a Set then you use:

    /// A member of the set, or `nil` if the set is empty.
    var first: T? { get }
    

    Get the 0th index or the 1,000,000th index makes no difference - they are all an arbitrary object.

    But, if you want repeated calls to return a likely different element each time, then first might not fit the bill.

    0 讨论(0)
  • 2021-01-04 06:54

    Probably the best approach is advance which walks successor for you:

    func randomElementIndex<T>(s: Set<T>) -> T {
        let n = Int(arc4random_uniform(UInt32(s.count)))
        let i = advance(s.startIndex, n)
        return s[i]
    }
    

    (EDIT: Heh; noticed you actually updated the question to include this answer before I added it to my answer... well, still a good idea and I learned something too. :D)

    You can also walk the set rather than the indices (this was my first thought, but then I remembered advance).

    func randomElement<T>(s: Set<T>) -> T {
        let n = Int(arc4random_uniform(UInt32(s.count)))
        for (i, e) in enumerate(s) {
            if i == n { return e }
        }
        fatalError("The above loop must succeed")
    }
    
    0 讨论(0)
  • 2021-01-04 06:56

    In swift 3

    extension Set {
        public func randomObject() -> Element? {
            let n = Int(arc4random_uniform(UInt32(self.count)))
            let index = self.index(self.startIndex, offsetBy: n)
            return self.count > 0 ? self[index] : nil
        }
    }
    
    0 讨论(0)
  • 2021-01-04 07:02

    As per comments above re Swift updates, used a minor change for an extension to Set:

    func randomElement() -> Element?
    {
        let randomInt = Int(arc4random_uniform(UInt32(self.count)))
        let index = startIndex.advancedBy(randomInt)
        return count == 0 ? nil: self[index]
    }
    
    0 讨论(0)
  • 2021-01-04 07:05

    Starting with Swift 4.2, you can use randomElement:

    let random = set.randomElement()
    
    0 讨论(0)
提交回复
热议问题