Сортировка словаря в Swift

Я знаю, что эта тема уже обсуждалась, но я не могу решить, глядя на другие ответы, поэтому заранее извините за мое созревание!

мне нужно отсортировать этот словарь по ключам

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

поэтому мне нужен такой словарь

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

но я не могу этого сделать.

Я пробовал это

let sortedKeysAndValues = sorted(dictionary) { .0 < .0 }

но после того, как мне нужно создать два массива из этого словаря (ключи и значения) и, используя это решение

codesArray = sortedKeysAndValues.keys.array

дать мне ошибка ' [(String, String)]' не имеет члена с именем 'keys' потому что это решение не совсем словарь.

так я попробовал другое решение:

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

, которая работает хорошо, но тогда я не знаю, как создать новый словарь стоимостьюs.

что самое лучшее решение? Как сделать это работает?

6 ответов


выход .0 < .0}) print(sortedArray) let keys = sortedArray.map {return .0 } print(keys) let values = sortedArray.map {return .1 } print(values)


словари не упорядочены. Если вы хотите перечислить их по порядку, вы можете сделать это, используя решение @HoaParis (что является моим предпочтением), а также

for (k,v) in sorted(codiceNomeDict, {.1 < .1}) { ... }

это немного лучше, чем то, что вы делали раньше, потому что он не создает временный массив.

но если вы действительно хотите "коллекцию, которая сопоставляет одно значение с другим и упорядочивается по его ключу", вам нужно создать для этого другую структуру данных. Так что давайте сделаем это. Это хороший опыт обучения.

эта версия просто реализует SequenceType и предоставляет индекс get/set, который является большей частью того, что вы обычно хотите. Что делает его полным CollectionType немного больно, я думаю, так как startIndex и endIndex hae, чтобы быть 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 }
        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

зачем вам беспокоиться о SortedDictionary когда у вас уже есть sorted()? Ну, обычно я бы не стал. Но это дает возможность для абстракции. Вы можете управлять порядком сортировки при создании объекта, а не при перечислении объектов. Вы можете потенциально кэшировать порядок сортировки (хотя я подозреваю, что в большинстве случаев это будет больно, а не поможет).

но я рекомендую просто использовать sorted в целом.


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

вы не можете сортировать словарь таким простым способом. Я думаю, что словарь использует какую-то структуру данных дерева. Но после сортировки вы получаете массив кортежей. Таким образом, вы можете получить ключи таким образом:

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

сортировка ключей по значению словаря на самом деле проще, чем кажется на первый:

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

и это все! Больше ничего нет.


сортировка ключей без учета регистра в 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))