Ordenar diccionario por claves

128

Quiero ordenar un diccionario en Swift. Tengo un diccionario como:

"A" => Array[]
"Z" => Array[]
"D" => Array[]

etc. Quiero que sea como

"A" => Array[]
"D" => Array[]
"Z" => Array[]

etc.

He intentado muchas soluciones en SO pero nadie trabajó para mí. Estoy usando XCode6 Beta 5 y en él algunos están dando error de compilación y algunas soluciones están dando excepciones. Entonces, cualquiera que pueda publicar la copia de trabajo de la clasificación del diccionario.

Aleem Ahmad
fuente
66
No se puede ordenar un diccionario, es un contenedor asociativo. Si necesita un pedido en particular, copie las claves en una matriz y ordénelas. Luego, repita las teclas y extraiga sus valores correspondientes.
dasblinkenlight
@dasblinkenlight Entonces, ¿puedes decirme cómo ordenar una matriz de manera rápida?
Aleem Ahmad
@AleemAhmad Echa un vistazo a esta respuesta , tiene sortedKeysfunción.
dasblinkenlight
@dasblinkenlight He intentado esto pero está dando error en [KeyType]
Aleem Ahmad

Respuestas:

167
let dictionary = [
    "A" : [1, 2],
    "Z" : [3, 4],
    "D" : [5, 6]
]

let sortedKeys = Array(dictionary.keys).sorted(<) // ["A", "D", "Z"]

EDITAR:

La matriz ordenada del código anterior contiene solo claves, mientras que los valores deben recuperarse del diccionario original. Sin embargo, 'Dictionary'también es un 'CollectionType'par de (clave, valor) y podemos usar la 'sorted'función global para obtener una matriz ordenada que contenga tanto claves como valores, de esta manera:

let sortedKeysAndValues = sorted(dictionary) { $0.0 < $1.0 }
println(sortedKeysAndValues) // [(A, [1, 2]), (D, [5, 6]), (Z, [3, 4])]

EDIT2: la sintaxis Swift cambiante mensual prefiere actualmente

let sortedKeys = Array(dictionary.keys).sort(<) // ["A", "D", "Z"]

Lo global sortedestá en desuso.

Ivica M.
fuente
Esto le brinda una variedad de claves. La matriz carece de los valores. Podrías buscar los valores del diccionario, supongo.
StilesCrisis
2
Tienes razón. Acabo de editar la publicación para proporcionar una solución para obtener una matriz de pares (clave, valor) ordenados por claves. Gracias por el comentario.
Ivica M.
@IvicaM. ¡Hola! Comprendí cómo puedo ordenar el diccionario por teclas, pero no entiendo cómo puedo ordenar una matriz de elementos en el diccionario. Por favor, ayúdame. Por ejemplo, contactos var privados: [(String, [User])] = []
Alexander Khitev
55
Swift 3 = Array (dictionary.keys) .sorted (by: <)
miff
44
A partir de Swift 4, puede escribirlet sortedKeys = dictionary.keys.sorted()
Code Different
113

Swift 2.0

Versión actualizada de la respuesta de Ivica M:

let wordDict = [
     "A" : [1, 2],
     "Z" : [3, 4],
     "D" : [5, 6]
]

let sortedDict = wordDict.sort { $0.0 < $1.0 }
print("\(sortedDict)") // 

Swift 3

wordDict.sorted(by: { $0.0 < $1.0 })

Aviso:

No se sorprenda de que el tipo resultante sea una matriz en lugar de un diccionario. ¡Los diccionarios no se pueden ordenar ! El tipo de datos resultante es una matriz ordenada, al igual que en la respuesta de @ Ivica.

Dan Beaulieu
fuente
26
esto en realidad devuelve una matriz de [(String, [Int])] no un diccionario
scord
44
los diccionarios realizados no están clasificados, por lo que no tiene mucho sentido recrear el tipo de datos de todos modos. Terminé simplemente guardando una serie de claves ordenadas.
scord
Obtengo Binary operator > can not be compared to two cualquier operandos. Downcasting tampoco funciona
Sean
27

Si desea iterar sobre las claves y los valores en un orden ordenado por clave, este formulario es bastante sucinto

let d = [
    "A" : [1, 2],
    "Z" : [3, 4],
    "D" : [5, 6]
]

for (k,v) in Array(d).sorted({$0.0 < $1.0}) {
    println("\(k):\(v)")
}
rks
fuente
ordenado es Método personalizado o ¿Qué? muestra error al implementar
rikky
@rikkyG Swift 1: sorty sorted. Swift 2: se sortha convertido sortInPlacey se sortedha convertido sort.
Eric Aya
14

En swift 4 puedes escribirlo de manera más inteligente:

let d = [ 1 : "hello", 2 : "bye", -1 : "foo" ]
d = [Int : String](uniqueKeysWithValues: d.sorted{ $0.key < $1.key })
Davide Gianessi
fuente
3
Gracias por el esfuerzo, pero antes que nada, "let" no crea el código, por lo que primero debe ser "var". Luego, después de que la compilación tenga éxito, este código no funciona, no clasifica el diccionario, obtengo el mismo resultado antes y después de ejecutar este código. Tal vez me estoy perdiendo algo, pero explique más o cambie el código. ======= var d = [1: "hola", 2: "adiós", -1: "foo"] imprimir (d) - >>> imprime [2: "adiós", -1: " foo ", 1:" hola "] d = [Int: String] (uniqueKeysWithValues: d.sorted {$ 0.key <$ 1.key}) print (d) - >>> imprime [2:" bye ", -1 : "foo", 1: "hola"]
KarimIhab
No es posible ya que cuando lo convierte de nuevo al diccionario, cambiará a la colección no ordenada ya que los diccionarios en
Swift
12

Intenté todo lo anterior, en pocas palabras todo lo que necesitas es

let sorted = dictionary.sorted { $0.key < $1.key }
let keysArraySorted = Array(sorted.map({ $0.key }))
let valuesArraySorted = Array(sorted.map({ $0.value }))

Elsammak
fuente
6

Para Swift 4, lo siguiente me ha funcionado:

let dicNumArray = ["q":[1,2,3,4,5],"a":[2,3,4,5,5],"s":[123,123,132,43,4],"t":[00,88,66,542,321]]

let sortedDic = dicNumArray.sorted { (aDic, bDic) -> Bool in
    return aDic.key < bDic.key
}
Shiv Kumar
fuente
55
Esto no devuelve un Diccionario, esto devolverá una serie de tuplas
Daniel Arantes Loverde
@DanielArantesLoverde Los diccionarios no se pueden ordenar por definición. Una serie de tuplas es lo mejor que puedes hacer.
John Montgomery
1
Lo sé, pero la pregunta pide un pedido, por lo que esta respuesta no es correcta. ¿Estás de acuerdo?
Daniel Arantes Loverde
6

Esta es una alternativa elegante para ordenar el diccionario en sí:

A partir de Swift 4 y 5

let sortedKeys = myDict.keys.sorted()

for key in sortedKeys {
   // Ordered iteration over the dictionary
   let val = myDict[key]
}
ThunderStruct
fuente
6

En Swift 5 , para ordenar el Diccionario por CLAVES

let sortedYourArray = YOURDICTIONARY.sorted( by: { $0.0 < $1.0 })

Para ordenar el Diccionario por VALORES

let sortedYourArray = YOURDICTIONARY.sorted( by: { $0.1 < $1.1 })
Abdul Karim Khan
fuente
4

Para Swift 3, el siguiente tipo retorna el diccionario ordenado por claves:

let unsortedDictionary = ["4": "four", "2": "two", "1": "one", "3": "three"]

let sortedDictionary = unsortedDictionary.sorted(by: { $0.0.key < $0.1.key })

print(sortedDictionary)
// ["1": "one", "2": "two", "3": "three", "4": "four"]
Arijan
fuente
10
Esto no devolverá un diccionario, devolverá una serie de
Tuplas
Ni siquiera leas la pregunta antes de poner tu respuesta. Estás perdiendo el tiempo de muchas personas aquí. Esta pregunta trata específicamente de ordenar un diccionario y obtener un diccionario ordenado, no una matriz. No sé por qué todos están dando respuestas incorrectas.
Shivam Pokhriyal
3

"ordenado" en iOS 9 y xcode 7.3, swift 2.2 es imposible, cambie "ordenado" a "ordenar", así:

let dictionary = ["main course": 10.99, "dessert": 2.99, "salad": 5.99]
let sortedKeysAndValues = Array(dictionary).sort({ $0.0 < $1.0 })
print(sortedKeysAndValues)

//sortedKeysAndValues = ["desert": 2.99, "main course": 10.99, "salad": 5.99]
AmyNguyen
fuente
3
El resultado de sortedKeysAndValues ​​no es un diccionario, ¡es una matriz!
Canal
2
El resultado es una Arrayde las Tuples, no unDictionary
2

Swift 5

Ingrese el diccionario que desea ordenar alfabéticamente por teclas.

// Sort inputted dictionary with keys alphabetically.
func sortWithKeys(_ dict: [String: Any]) -> [String: Any] {
    let sorted = dict.sorted(by: { $0.key < $1.key })
    var newDict: [String: Any] = [:]
    for sortedDict in sorted {
        newDict[sortedDict.key] = sortedDict.value
    }
    return newDict
}

dict.sorted (por: {$ 0.key <$ 1.key}) por sí mismo devuelve una tupla (valor, valor) en lugar de un diccionario [valor: valor]. Por lo tanto, el bucle for analiza la tupla para que regrese como un diccionario. De esa manera, pones un diccionario y recuperas un diccionario.

Krekin
fuente
2

Swift 4 y 5

Para la clasificación de claves de cadena:

dictionary.keys.sorted(by: {$0.localizedStandardCompare($1) == .orderedAscending})

Ejemplo:

var dict : [String : Any] = ["10" : Any, "2" : Any, "20" : Any, "1" : Any]

dictionary.keys.sorted() 

["1" : Any, "10" : Any, "2" : Any, "20" : Any]

dictionary.keys.sorted(by: {$0.localizedStandardCompare($1) == .orderedAscending})

["1" : Any, "2" : Any, "10" : Any, "20" : Any]

Xav Mac
fuente
1

Para Swift 3, lo siguiente me funcionó y la sintaxis de Swift 2 no funcionó:

// menu is a dictionary in this example

var menu = ["main course": 10.99, "dessert": 2.99, "salad": 5.99]

let sortedDict = menu.sorted(by: <)

// without "by:" it does not work in Swift 3
Joeri
fuente
Esta respuesta es bastante incompleta. ¿Qué es sortedDict? ¿Qué es menu? Este código tampoco parece ser válido.
random_user_name
Algo más serio ahora: un diccionario no tiene orden . Lo que obtienes con tu código es una serie de tuplas, no un diccionario ordenado, como ya se dijo en algunas respuestas y comentarios.
Eric Aya
el tema es: ordenar el diccionario por teclas, estoy respondiendo a este tema. Y es un comentario específico sobre solo un cambio de sintaxis en Swift 3, no niega nada de lo que se ha escrito antes.
Joeri
"Esta respuesta es bastante incompleta. ¿Qué está ordenado? ¿Qué es el menú? Este código tampoco parece ser válido. - cale_b" La respuesta fue editada, lo único que faltaba era una declaración para un menú de dicción. Pensé que estaba claro, esto solo se trata de un cambio de sintaxis en Swift 3 como se indica. El código funciona en Swift 3.
Joeri
alguna sugerencia para swift 4 por favor?
famfamfam
1

Swift 3 está ordenado (por: <)

let dictionary = [
    "A" : [1, 2],
    "Z" : [3, 4],
    "D" : [5, 6]
]

let sortedKeys = Array(dictionary.keys).sorted(by:<) // ["A", "D", "Z"]
Shadros
fuente