arrays - 词典数组中最常见的词典

标签 arrays swift dictionary

我需要在一系列 swift 字典中找到最常用的字典。我尝试使用以下内容:

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 }
            }

但我无法使用 [[String:String]]() 类型的参数列表调用“频率”。我如何编辑上述函数以获取字典数组,或完全使用另一种方法?

最佳答案

正如评论所提到的,问题在于类型[String:String] 不是Hashable

当您的类型不可哈希时,一个(非常)低效的解决方案是回退到 Comparable(可以排序并生成运行总计)或 Equatable 或者,最坏的情况,要求调用者提供一个 isEquivalent 闭包。然后,您将搜索运行频率以寻找等效项(如果找不到,则以频率 1 插入)。

这是在 Swift 2.0 中执行此操作的实现:

extension SequenceType {
    func frequencies(@noescape isEquivalent: (Generator.Element,Generator.Element) -> Bool) -> [(Generator.Element,Int)] {
        var frequency: [(Generator.Element,Int)] = []

        for x in self {
            // find the index of the equivalent entry
            if let idx = frequency.indexOf({ isEquivalent($0.0, x)}) {
                // and bump the frequency
                frequency[idx].1 += 1
            }
            else {
                // add a new entry
                frequency.append(x,1)
            }

        }

        return frequency.sort { $0.1 > $1.1 }
    }
}

因为 == 有一个比较两个字典的实现,只要那些字典包含相等的值,你就可以这样调用它:

let dicts = [
    ["name": "David", "number": "1"],
    ["name": "John", "number": "2"],
    ["name": "David", "number": "1"],
]

// you can use `==` in two dictionaries that contain an equatable value,
// such as String here:
dicts[0] == dicts[1]  // false
dicts[0] == dicts[2]  // true

// so you can call frequencies like so:
dicts.frequencies(==)

返回:

[(["number": "1", "name": "David"], 2), 
 (["number": "2", "name": "John"], 1)]

编辑:这是一个 Swift 1.2 版本,不幸的是,由于 1.2 中缺少带有谓词的 find 版本(在 2.0 中重命名为 indexOf)而变得复杂。这应该可以工作,但我在这台机器上没有 1.2 的工作副本,因此您可能需要修复任何语法错误:

extension Array {
    // add missing indexOf to Array as 1.2 doesn't have an equivalent
    func indexOf(@noescape predicate: T->Bool) -> Int? {
        for idx in indices(self) {
            if predicate(self[idx]) { return idx }
        }
        return nil
    }

}

func frequencies<S: SequenceType>
    (source: S, @noescape isEquivalent: (S.Generator.Element,S.Generator.Element) -> Bool) -> [(S.Generator.Element,Int)] {

        var frequency: [(S.Generator.Element,Int)] = []

        for x in source {
            // find the index of the equivalent entry
            if let idx = frequency.indexOf({ isEquivalent($0.0, x)}) {
                // and bump the frequency
                frequency[idx].1 += 1
            }
            else {
                // add a new entry
                frequency.append(x,1)
            }

        }

        return sorted(frequency) { $0.1 > $1.1 }
}

frequencies(dicts, ==)

关于arrays - 词典数组中最常见的词典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30945685/

相关文章:

python - 改变值检测 numpy Python

每个函数内的 Javascript jQuery 数组函数

ios - 为什么 touchDragExit 和 touchDragEnter 被多次重复调用?

ios - 水平 StackView 的正确对齐和分布选择

python - 属性错误 : 'dict' object has no attribute 'charss'

python - 从python中的嵌套字典创建层次树

arrays - 如何根据每个数组中不超过特定总和的值将哈希拆分为多个键数组?

javascript - Eloquent Javascript,listToArray。当输入数组有超过 3 个元素时,为什么我的 for 循环返回 rest [object]

Swift:CoreData - 插入行时发送到实例的无法识别的选择器

c# - 您如何将与集合中其他项目具有依赖性的项目分组?