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

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

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

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

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

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

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

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

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

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

codesArray = sortedKeysAndValues.keys.array

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

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

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

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

Какое лучшее решение? Как заставить его работать?

Ответ 1

Вывод функции sorted выше - Массив. Таким образом, вы не можете получить ключи и значения, например Словарь. Но вы можете использовать функцию map для извлечения этих отсортированных ключей и значений

Возвращает массив, содержащий отсортированные элементы source {согласно}. Алгоритм сортировки нестабилен (можно изменить относительный порядок элементы, для которых 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)

Ответ 2

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

for (k,v) in sorted(codiceNomeDict, {$0.1 < $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 < $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

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

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

Ответ 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

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

    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 }

Ответ 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

Вот функция, которая возвращает нечувствительный к регистру отсортированный массив ключей (или любые значения String).

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

 /// 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))