在Swift中对包含更复杂值的字典进行排序

时间:2015-03-04 15:52:08

标签: sorting swift dictionary key

根据提供here的示例,根据字典值的简单双打或Ints的键排序工作完全正常....

但是更复杂的字典结构呢?

我有一个字典值的字典,每个字典都包含一个Double-Tuples数组。 (相当复杂,我知道......)。 我想根据Second-Tuple-Array的总和对字典值进行排序。 (即所有第二元组元素形成一个数组,并且对该数组求和;然后根据最小值对数组求和进行排序)。但所有这些仍然没有丢失关于​​字典密钥的信息。 ask方法的结果应该根据“second-tuple-summed-up-array-results”的排序结果返回一个键数组。

这是我对这个问题的“差”试验: 我尝试使用以下Playground示例(见下文)根据元组数组的第一元组的值对键进行排序。但它还没有表现......

这适用于基本类型:

extension Dictionary {
    func keysSortedByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
        return sorted(self) {
            let (lk, lv) = $0
            let (rk, rv) = $1
            return isOrderedBefore(lv, rv)
        }.map { (k,v) in k }
    }
}

let dict = ["a":2, "c":1, "b":3]
dict.keysSortedByValue(<)  // result array of keys: ["c", "a", "b"]
dict.keysSortedByValue(>)  // result array of keys: ["b", "a", "c"]

但在我更复杂的情况下,它不起作用:

var criteria_array1 = [(Double, Double)]()
var criteria_array2 = [Double]()
var criteria_dict1 = [String:[(Double, Double)]]()
var criteria_dict2 = [String:[Double]]()

// Random creation of two dictionaries with a complex value-structure...
// Dictionary1: keys = Strings, values = array of Double-Tuples
// Dictionary2: keys = Strings, values = array of Doubles
for n in 1...5 {
    let currentTopoString: String = "topo_\(n)"
    for t in 0...14 {
        let a: Double = Double(arc4random_uniform(1000))
        let b: Double = Double(Double(arc4random_uniform(1000))/1000)
        criteria_array1 += [(a, b)]
        criteria_array2 += [b]
    }
    criteria_dict1[currentTopoString] = criteria_array1
    criteria_dict2[currentTopoString] = criteria_array2
    criteria_array1.removeAll()
    criteria_array2.removeAll()
}

// the two following instruction generate compiler errors....
// why ???????????
// How could a complex dictionary-value-structure be applied to a sortingMethod ??
criteria_dict1.keysSortedByFirstTupleValue(>)
criteria_dict2.keysSortedByFirstTupleValue(>)

1 个答案:

答案 0 :(得分:1)

这是适当实施isOrderedBefore功能的问题。只是传递>不会削减它(即使假设元组数组有>的实现,它几乎肯定不会进行你正在寻找的总和的比较对)。

如果我正确理解了您的目标,您希望根据元组数组中某个元组条目之和的值对键进行排序?

这样的事情:

criteria_dict1.keysSortedByValue { lhs, rhs in
    // if you actually want to sort by sum of first element in tuple,
    // change next.1 to next.0
    let left_sum = reduce(lhs, 0) { total, next in total + next.1 }
    let right_sum = reduce(rhs, 0) { total, next in total + next.1 }
    return left_sum > right_sum
}

这是非常低效的,因为你为每次比较总结了数组 - 实际上你可能想要记住它,或者如果你经常这样做,可能会根据不同的数据结构重新思考问题。 / p>