Classificar dicionário por chaves

128

Quero classificar um dicionário no Swift. Eu tenho um dicionário como:

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

etc Eu quero que seja

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

etc.

Eu tentei muitas soluções em SO, mas ninguém trabalhou para mim. Estou usando o XCode6 Beta 5 e nele alguns estão dando erro de compilador e algumas soluções estão dando exceções. Portanto, qualquer pessoa que possa postar a cópia de trabalho da classificação do dicionário.

Aleem Ahmad
fonte
6
Você não pode classificar um dicionário, é um contêiner associativo. Se você precisar de um pedido específico, copie as chaves em uma matriz e classifique-as. Em seguida, itere sobre as teclas e puxe seus valores correspondentes.
precisa saber é o seguinte
@dasblinkenlight Então, você pode me dizer como classificar uma matriz rapidamente?
Aleem Ahmad
@AleemAhmad Dê uma olhada nesta resposta , ela tem sortedKeysfunção.
precisa saber é o seguinte
@dasblinkenlight Eu tentei isso, mas está dando erro no [KeyType] #
Aleem Ahmad

Respostas:

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

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

EDITAR:

A matriz classificada do código acima contém apenas chaves, enquanto os valores precisam ser recuperados do dicionário original. No entanto, 'Dictionary'também é um 'CollectionType'dos pares (chave, valor) e podemos usar a 'sorted'função global para obter uma matriz classificada contendo chaves e valores, assim:

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

EDIT2: a mudança mensal da sintaxe Swift atualmente prefere

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

O global sortedestá obsoleto.

Ivica M.
fonte
Isso fornece uma matriz de chaves. A matriz está sem os valores. Você poderia procurar os valores do dicionário, eu acho.
StilesCrisis
2
Você está certo. Acabei de editar o post para fornecer uma solução para obter uma matriz de pares (chave, valor) ordenada por chaves. Obrigado pelo comentário.
Ivica M.
@IvicaM. Olá! Entendi como posso classificar o dicionário por chaves, mas não entendo como classificar a matriz de elementos no dicionário. Por favor me ajude. Por exemplo, var privada contatos: [(String, [usuário])] = []
Alexander Khitev
5
Swift 3 = Matriz (dictionary.keys) .sorted (por: <)
miff
4
No Swift 4, você pode escrever #let sortedKeys = dictionary.keys.sorted()
Code Different
113

Swift 2.0

Versão atualizada da resposta 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 prévio:

Não se surpreenda que o tipo resultante seja uma matriz e não um dicionário. Os dicionários não podem ser classificados ! O tipo de dados resultante é uma matriz classificada, exatamente como na resposta da @ Ivica.

Dan Beaulieu
fonte
26
isso realmente retorna uma matriz de [(String, [Int])] que não é um dicionário
scord 12/02/16
4
Os dicionários realizados não são classificados, portanto, não faz muito sentido recriar o tipo de dados. Acabei salvando uma matriz de chaves classificadas.
Scord 12/02/16
Eu recebo Binary operator > can not be compared to two qualquer operando. O downcasting também não funciona #
Sean
27

Se você deseja iterar sobre as chaves e os valores em uma ordem de chave, este formulário é 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
fonte
classificado é método personalizado ou o quê? ele está mostrando erro ao implementar
Rikky
@rikkyG Swift 1: sorte sorted. Swift 2: sorttornou-se sortInPlacee sortedtornou-se sort.
Eric Aya
14

No swift 4, você pode escrevê-lo de maneira mais inteligente:

let d = [ 1 : "hello", 2 : "bye", -1 : "foo" ]
d = [Int : String](uniqueKeysWithValues: d.sorted{ $0.key < $1.key })
Davide Gianessi
fonte
3
Obrigado pelo esforço, mas antes de tudo, o "let" não cria o código, então primeiro ele precisa ser "var". Então, depois que a compilação é bem-sucedida, esse código não funciona, não classifica o dicionário, eu recebo o mesmo resultado antes e depois de executar esse código. Talvez esteja faltando alguma coisa, mas por favor elabore mais ou altere o código. ======= var d = [1: "olá", 2: "tchau", -1: "foo"] print (d) - >>> imprime [2: "tchau", -1: " foo ", 1:" olá "] d = [Int: String] (uniqueKeysWithValues: d.sorted {$ 0.key <$ 1.key}) print (d) - >>> imprime [2:" bye ", -1 : "foo", 1: "olá"]
KarimIhab 26/07/18
Não é possível, como quando você convertê-lo de volta ao dicionário que vai mudar para a coleção não ordenada como dicionários em rápida são desordenada coleção developer.apple.com/documentation/swift/dictionary
Jaimin
12

Eu tentei todas as opções acima, em poucas palavras, tudo o que você precisa é

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

Elsammak
fonte
6

Para o Swift 4, o seguinte funcionou para mim:

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
fonte
5
Esta não retorna um dicionário, isso irá retornar uma matriz de tuplas
Daniel Arantes Loverde
Os dicionários @DanielArantesLoverde não são classificáveis ​​por definição. Uma matriz de tuplas é o melhor que você pode fazer.
John Montgomery
1
Eu sei disso, mas a pergunta pede um pedido, então esta resposta não está correta. Você concorda?
Daniel Arantes Loverde 01/05/19
6

Esta é uma alternativa elegante para classificar o próprio dicionário:

A partir dos Swift 4 e 5

let sortedKeys = myDict.keys.sorted()

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

No Swift 5 , para classificar Dictionary by KEYS

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

Para classificar Dicionário por VALUES

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

Para o Swift 3, a seguinte classificação retorna o dicionário classificado por chaves:

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
fonte
10
Esta rotina voltar um dicionário, este irá retornar uma matriz de tuplos
anoop4real
Você nem leu a pergunta antes de responder. Você está perdendo tempo com muitas pessoas aqui. Esta pergunta é especificamente sobre a classificação de um dicionário e a obtenção de um dicionário classificado e não da matriz. Não sei por que todo mundo está colocando respostas erradas.
Shivam Pokhriyal 14/09/19
3

"classificado" no iOS 9 e xcode 7.3, o swift 2.2 é impossível, altere "classificado" para "classificar", assim:

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
fonte
3
O resultado de selectedKeysAndValues ​​não é um dicionário, é uma Matriz!
Canal
2
O resultado é um Arrayde Tuples, não umDictionary
2

Swift 5

Insira o seu dicionário que você deseja classificar em ordem alfabética 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 si próprio retorna uma tupla (valor, valor) em vez de um dicionário [valor: valor]. Assim, o loop for analisa a tupla para retornar como um dicionário. Dessa forma, você coloca um dicionário e recebe um dicionário de volta.

Krekin
fonte
2

Swift 4 e 5

Para classificação de chaves de cadeia:

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

Exemplo:

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
fonte
1

Para o Swift 3, o seguinte funcionou para mim e a sintaxe do Swift 2 não funcionou:

// 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
fonte
Esta resposta é bastante incompleta. O que é sortedDict? O que é menu? Este código também não parece ser válido.
Random_user_name 12/08
Algo mais sério agora: um dicionário não tem ordem . O que você obtém com seu código é uma matriz de tuplas, não um dicionário classificado - como já foi dito em algumas respostas e comentários.
Eric Aya
o tópico é: classificar dicionário por chaves, estou respondendo a esse tópico. E é uma observação específica referente apenas a uma mudança de sintaxe no Swift 3, que não nega nada do que foi escrito antes.
Joeri
"Esta resposta é bastante incompleta. O que é ordenadoDict? O que é menu? Esse código também não parece ser válido. - cale_b" A resposta foi editada, a única coisa que faltava era uma declaração para um menu de dicção. Eu pensei que estava claro, isso é apenas uma alteração de sintaxe no Swift 3, conforme indicado. O código funciona na Swift 3.
Joeri
alguma sugestão para swift 4 plz?
Famfamfam 19/09/19
1

Swift 3 é classificado (por: <)

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

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