Most common array elements

前端 未结 3 1184
南笙
南笙 2020-12-11 08:36

I need to find the most common (modal) elements in an array.

The simplest way I could think of was to set variables for each unique element, and assign a count vari

相关标签:
3条回答
  • 2020-12-11 08:47

    edit: now with Swift 2.0 below

    Not the most efficient of solutions but a simple one:

    let a = [1,1,2,3,1,7,4,6,7,2]
    
    var frequency: [Int:Int] = [:]
    
    for x in a {
        // set frequency to the current count of this element + 1
        frequency[x] = (frequency[x] ?? 0) + 1
    }
    
    let descending = sorted(frequency) { $0.1 > $1.1 }
    

    descending now consists of an array of pairs: the value and the frequency, sorted most frequent first. So the “top 5” would be the first 5 entries (assuming there were 5 or more distinct values). It shouldn't matter how big the source array is.

    Here's a generic function version that would work on any sequence:

    func frequencies
      <S: SequenceType where S.Generator.Element: Hashable>
      (source: S) -> [(S.Generator.Element,Int)] {
    
        var frequency: [S.Generator.Element:Int] = [:]
    
        for x in source {
            frequency[x] = (frequency[x] ?? 0) + 1
        }
    
        return sorted(frequency) { $0.1 > $1.1 }
    }
    
    frequencies(a)
    

    For Swift 2.0, you can adapt the function to be a protocol extension:

    extension SequenceType where Generator.Element: Hashable {
        func frequencies() -> [(Generator.Element,Int)] {
    
            var frequency: [Generator.Element:Int] = [:]
    
            for x in self {
                frequency[x] = (frequency[x] ?? 0) + 1
            }
    
            return frequency.sort { $0.1 > $1.1 }
        }
    }
    
    a.frequencies()
    

    For Swift 3.0:

    extension Sequence where Self.Iterator.Element: Hashable {
        func frequencies() -> [(Self.Iterator.Element,Int)] {
    
            var frequency: [Self.Iterator.Element:Int] = [:]
    
            for x in self {
                frequency[x] = (frequency[x] ?? 0) + 1
            }
    
            return frequency.sorted { $0.1 > $1.1 }
        }
    }
    
    0 讨论(0)
  • 2020-12-11 08:56

    Same as Airspeed Velocity, using a reduce instead of for-in:

    extension Sequence where Self.Iterator.Element: Hashable {
        func frequencies() -> [(Self.Iterator.Element, Int)] {
            return reduce([:]) {
                var frequencies = $0
                frequencies[$1] = (frequencies[$1] ?? 0) + 1
                return frequencies
            }.sorted { $0.1 > $1.1 }
        }
    }
    

    But please note that, here, using reduce with a struct is not as efficient as a for-in because of the struct copy cost. So you will generally prefer the for-in way of doing it.

    [edit: gosh, the article is by the same guy as the top answer!]

    0 讨论(0)
  • 2020-12-11 09:06

    For XCode 7.1 the solution is.

    // Array of elements
    let a = [7,3,2,1,4,6,8,9,5,3,0,7,2,7]
    
    // Create a key for elements and their frequency
    var times: [Int: Int] = [:]
    
    // Iterate over the dictionary
    for b in a {
        // Every time there is a repeat value add one to that key
        times[b] = (times[b] ?? 0) + 1
    }
    
    // This is for sorting the values
    let decending = times.sort({$0.1 > $1.1})
    // For sorting the keys the code would be 
    // let decending = times.sort({$0.0 > $1.0})
    // Do whatever you want with sorted array
    print(decending)
    
    0 讨论(0)
提交回复
热议问题