【问题标题】:Sort a Dictionary in Swift在 Swift 中对字典进行排序
【发布时间】:2015-07-15 07:09:23
【问题描述】:

我知道这个话题已经讨论过了,但我无法解决寻找其他答案,所以提前为我的成熟感到抱歉!

我需要按键排序这个字典

codeValueDict = ["us": "$", "it": "€", "fr": "€"]

所以我需要这样的字典

sortedDict = ["fr": "€", "it": "€", "us": "$"]

但我做不到。

我试过了

let sortedKeysAndValues = sorted(dictionary) { $0.0 < $1.0 }

但是在我需要从这个字典(键和值)创建两个数组并使用该解决方案之后

codesArray = sortedKeysAndValues.keys.array

给我错误'[(String, String)]' does not have a member named 'keys' 因为该解决方案不完全返回字典。

所以我尝试了另一种解决方案:

    let prova = codiceNomeDict as NSDictionary
    for (k,v) in (Array(codiceNomeDict).sorted {$0.1 < $1.1}) {
        let value = "[\"\(k)\": \"\(v)\"]"
        println(value)
    }

这很好用,但我不知道如何创建一个新的 values 字典。

最好的解决方案是什么?如何让它发挥作用?

【问题讨论】:

  • 您需要回到您要解决的问题。在您的示例中,codeValueDictsortedDict 是完全相同的字典(因此,当您说“我需要这样的字典”时,您就有了)。您需要解决的问题是您要排序的内容。您的意思是要以特定顺序枚举值,还是您的意思是您想要以特定顺序的字符串表示形式,还是其他?这个函数的输出应该是什么?没有“有序字典”之类的东西。这在 Swift 中没有任何意义。

标签: swift sorting dictionary


【解决方案1】:

您不能以如此简单的方式对字典进行排序。我认为字典正在使用某种树数据结构。但是在排序之后你会得到一个元组数组。所以你可以通过这种方式获取密钥:

    let codeValueDict = ["us": "$", "it": "€", "fr": "€"]
    let sortedKeysAndValues = sorted(codeValueDict) { $0.0 < $1.0 }
    let keys = sortedKeysAndValues.map {$0.0 }
    let values = sortedKeysAndValues.map {$0.1 }

【讨论】:

  • 太棒了!你知道一种按值而不是键排序的方法吗?
  • { $0.0 &lt; $1.0 } 替换为{ $0.1 &lt; $1.1 } 以按值排序
【解决方案2】:

上面sorted函数的输出是一个数组。所以你不能像 Dictionary 那样获取键和值。但是您可以使用map 函数来检索那些排序的键和值

返回一个包含source{according} 的已排序元素的数组。 排序算法不稳定(可以改变相对顺序 isOrderedBefore 不为其建立顺序的元素)。

let codeValueDict = ["us": "$", "it": "€", "fr": "€"]

let sortedArray = sorted(codeValueDict, {$0.0 < $1.0})
print(sortedArray)

let keys = sortedArray.map {return $0.0 }
print(keys)

let values = sortedArray.map {return $0.1 }
print(values)

【讨论】:

【解决方案3】:

Swift 不包含排序的字典类型,并且字典无法排序。您可以通过执行以下操作添加提供对[(Key, Value)] 排序的扩展:

extension Dictionary {

    func sort(isOrderedBefore: (Key, Key) -> Bool) -> [(Key, Value)] {
        var result: [(Key, Value)] = []
        let sortedKeys = keys.array.sorted(isOrderedBefore)
        for key in sortedKeys {
            result.append(key, self[key]!)
        }
        return result
    }
}

【讨论】:

    【解决方案4】:

    字典没有排序。如果您想按顺序枚举它们,您可以使用@HoaParis 的解决方案(这是我的偏好),或者也可以

    for (k,v) in sorted(codiceNomeDict, {$0.1 < $1.1}) { ... }
    

    这只是比你以前做的更好一点,因为它不会生成临时数组。

    但是,如果您真的想要“一个将一个值映射到另一个值并按其键排序的集合”,那么您需要为此创建一些其他数据结构。所以让我们这样做。这是一次很好的学习经历。

    这个版本只实现了SequenceType 并提供了一个get/set 下标,这是您通常想要的大部分内容。我认为把它变成一个完整的CollectionType 有点痛苦,因为startIndexendIndex 是O(1)。可能的;比我今天早上想做的还多。

    注意Key: Comparable 的主要添加。这就是为什么Dictionary 不能 被订购。没有保证您可以对他们的密钥进行排序。通过添加该要求,我们可以。

    struct SortedDictionary<Key: Hashable, Value where Key: Comparable>: SequenceType {
        private var dict: Dictionary<Key, Value>
        init(_ dict: Dictionary<Key, Value>) {
            self.dict = dict
        }
        func generate() -> GeneratorOf<(Key, Value)> {
            let values = Array(zip(self.dict.keys, self.dict.values))
                .sorted {$0.0 < $1.0 }
            return GeneratorOf(values.generate())
        }
        subscript(key: Key) -> Value? {
            get        { return self.dict[key] }
            set(value) { self.dict[key] = value }
        }
    }
    
    var codeValueDict = ["us": "$", "it": "€", "fr": "€"]
    var sortedDict = SortedDictionary(codeValueDict)
    for (k, v) in sortedDict {
        println("\(k) => \(v)")
    }
    sortedDict["us"]
    sortedDict["ab"] = "!"
    sortedDict
    

    既然您已经拥有sorted(),为什么还要打扰SortedDictionary?嗯,通常我不会。但它确实提供了抽象的机会。您可以在对象创建时而不是在对象枚举时控制排序顺序。您可能会缓存排序顺序(尽管我怀疑在大多数情况下会伤害而不是帮助)。

    但我建议一般只使用sorted

    【讨论】:

      【解决方案5】:

      按字典的值对键进行排序实际上比最初看起来要简单:

      let yourDict = ["One": "X", "Two": "B", "Three": "Z", "Four": "A"]
      let sortedKeys = yourDict.keys.sort({ (firstKey, secondKey) -> Bool in
          return yourDict[firstKey] < yourDict[secondKey]
      })
      

      就是这样!真的没什么。

      【讨论】:

        【解决方案6】:

        在 Swift 2 中排序键不区分大小写

        这是一个函数,它返回一个 不区分大小写 排序的键数组(或任何字符串值)。

        请记住,Swift 的字典数据结构不能按键排序存储在内存中。所以是的,你可以通过键对其进行排序,但如果你打印它,那么键顺序又是随机的。

         /// returns an array of values sorted by values case-insensitive
        func sortCaseInsensitive(values:[String]) -> [String]{
        
            let sortedValues = values.sort({ (value1, value2) -> Bool in
        
                if (value1.lowercaseString < value2.lowercaseString) {
                    return true
                } else {
                    return false
                }
            })
            return sortedValues
        }
        

        调用

            let dict = ["world": "Hello!", "foo": "bar", "zYeah": "a", "akey": "xval"]
            let sortedKeys = sortCaseInsensitive(Array(dict.keys))
        

        【讨论】:

          猜你喜欢
          • 2018-07-17
          • 2014-07-28
          • 2015-09-28
          • 1970-01-01
          • 2016-07-14
          • 2020-11-10
          • 2017-01-22
          • 2023-04-05
          相关资源
          最近更新 更多