获得最常见的数组值

aig*_*tti 6 arrays sorting swift

我有一个数字数组,我想知道这个数组中最常见的数字.数组有时有5-6个整数,有时它有10-12个,有时甚至更多 - 数组中的整数也可能不同.所以我需要一个可以使用不同长度和数组值的函数.

一个例子:

myArray = [0, 0, 0, 1, 1]
Run Code Online (Sandbox Code Playgroud)

另一个例子:

myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
Run Code Online (Sandbox Code Playgroud)

现在我正在寻找一个给出0(在第一个例子中)的函数Integer,因为它在这个数组中是3次,而数组中的另一个整数(1)在数组中只有2次.或者对于第二个例子,它将是4.

看起来很简单,但我找不到解决方案.在网络上找到了一些例子,其解决方案是使用字典或解决方案很简单 - 但我似乎无法使用它与Swift 3 ...

但是,我没有找到适合我的解决方案.有人知道如何在整数数组中获得最频繁的整数?

Luc*_*tti 19

你也可以使用NSCountedSet,这里是代码

let nums = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
let countedSet = NSCountedSet(array: nums)
let mostFrequent = countedSet.max { countedSet.count(for: $0) < countedSet.count(for: $1) }
Run Code Online (Sandbox Code Playgroud)

感谢@Ben Morrow在下面的评论中提出了明智的建议.

  • 谢谢 !直到现在才知道CountedSet,很有提示.:-) (2认同)
  • @appzYourLife Cool 我还想到了另一种优化。您可以在 `countedSet` 上调用 `max(by:)` 而不是 `nums`。这样,它只需运行每个唯一元素一次,而不是遍历“nums”中的所有元素。这一更改将产生结果的速度提高 10 倍:0.001598 秒 vs 0.013010 秒。刚刚学会了甜蜜的[基准测试技巧](http://stackoverflow.com/questions/39115192/should-i-prefer-joined-or-flatmap-in-swift-3/39130099#39130099) (2认同)

vac*_*ama 18

let myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]

// Create dictionary to map value to count   
var counts = [Int: Int]()

// Count the values with using forEach    
myArray.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }

// Find the most frequent value and its count with max(by:)    
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
    print("\(value) occurs \(count) times")
}
Run Code Online (Sandbox Code Playgroud)

输出:

4 occurs 4 times
Run Code Online (Sandbox Code Playgroud)

这是一个功能:

func mostFrequent(array: [Int]) -> (value: Int, count: Int)? {
    var counts = [Int: Int]()

    array.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }

    if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
        return (value, count)
    }

    // array was empty
    return nil
}

if let result = mostFrequent(array: [1, 3, 2, 1, 1, 4, 5]) {
    print("\(result.value) occurs \(result.count) times")    
}
Run Code Online (Sandbox Code Playgroud)
1 occurs 3 times
Run Code Online (Sandbox Code Playgroud)

Swift 4的更新:

Swift 4引入reduce(into:_:)了数组查找的默认值,使您能够在一个有效的行中生成频率.我们也可以将它设为通用的,并使其适用于以下任何类型Hashable:

func mostFrequent<T: Hashable>(array: [T]) -> (value: T, count: Int)? {

    let counts = array.reduce(into: [:]) { $0[$1, default: 0] += 1 }

    if let (value, count) = counts.max(by: { $0.1 < $1.1 }) {
        return (value, count)
    }

    // array was empty
    return nil
}

if let result = mostFrequent(array: ["a", "b", "a", "c", "a", "b"]) {
    print("\(result.value) occurs \(result.count) times")
}
Run Code Online (Sandbox Code Playgroud)
a occurs 3 times
Run Code Online (Sandbox Code Playgroud)


and*_*n22 8

最常见的值称为"模式".这是一个简洁的版本:

let mode = myArray.reduce([Int: Int]()) { 
    var counts = $0    
    counts[$1] = ($0[$1] ?? 0) + 1
    return counts 
}.max { $0.1 < $1.1 }?.0
Run Code Online (Sandbox Code Playgroud)

这被认为是"不可读"还是"优雅"取决于你对更高阶功能的感受.尽管如此,这里它是扩展中的泛型方法Array(因此它适用于任何Hashable元素类型):

extension Array where Element: Hashable {
    var mode: Element? {
        return self.reduce([Element: Int]()) { 
            var counts = $0
            counts[$1] = ($0[$1] ?? 0) + 1 
            return counts 
        }.max { $0.1 < $1.1 }?.0
    }
}
Run Code Online (Sandbox Code Playgroud)

.0如果你想要一个包含模式计数的元组,只需删除它.

  • 我相信高阶函数非常优雅; 使用`;`强制尽可能多地包含在单个可怕的长行中,但不是那么多.我编辑了你的答案以增加可读性,如果你觉得它不合适,可以反转编辑.(解决方案为+1,之前仅适用于格式化:) (2认同)

小智 6

我对 Swift 5 的看法:

extension Collection {

    /**
     Returns the most frequent element in the collection.
     */
    func mostFrequent() -> Self.Element?
    where Self.Element: Hashable {
        let counts = self.reduce(into: [:]) {
            return $0[$1, default: 0] += 1
        }

        return counts.max(by: { $0.1 < $1.1 })?.key
    }
}
Run Code Online (Sandbox Code Playgroud)