2015-11-23 2 views
2

Я хотел бы перебрать ключи словаря, сначала сортируется по значению (по убыванию), а затем с помощью клавиши (по возрастанию)
let dict = ["foo" : 1, "bar" : 1, "baz" : 2, "qux" : 2]Swift: Сортировка ключи словаря по значению, а затем по ключевому

порядок итерации должен быть:
["baz", "qux", "bar", "foo"]

Я хотел бы напечатать:

baz 2 
qux 2 
bar 1 
foo 1 

ответ

6

Xcode 8 бета-6 • Swift 3

extension Dictionary where Value: Comparable { 
    var valueKeySorted: [(Key, Value)] { 
     return sorted{ if $0.value != $1.value { return $0.value > $1.value } else { return String(describing: $0.key) < String(describing: $1.key) } } 
    } 
} 

let dict = ["foo" : 1, "bar" : 1, "baz" : 2, "qux" : 2] 

let keyValueArray = dict.valueKeySorted 

print(keyValueArray) // "[("baz", 2), ("qux", 2), ("bar", 1), ("foo", 1)]" 

for (key, value) in keyValueArray { 
    print(key, value) 
} 


Xcode 2.x

let keyValueArray = dict.sort{ $0.0 < $1.0 }.sort{ $0.1 > $1.1} 
print(keyValueArray) // [(.0 "baz", .1 2), (.0 "qux", .1 2), (.0 "bar", .1 1), (.0 "foo", .1 1)] 

Вы также можете создать расширение, где словари значения сопоставимы:

extension Dictionary where Value: Comparable { 
    var valueKeySorted: [(Key, Value)] { 
     return sort{ $0.1 > $1.1 }.sort{ String($0.0) < String($1.0) } 
    } 
    // or sorting as suggested by Just Another Coder without using map 
    var valueKeySorted2: [(Key, Value)] { 
     return sort{ if $0.1 != $1.1 { return $0.1 > $1.1 } else { return String($0.0) < String($1.0) } } 
    } 


} 

использование:

let dict = ["foo" : 1, "bar" : 1, "baz" : 2, "qux" : 2] 

let keyValueArray = dict.valueKeySorted 

print(keyValueArray) // "[("baz", 2), ("qux", 2), ("bar", 1), ("foo", 1)]" 

Если вы хотите перебрать keyValueArray кортежей

for (key, value) in keyValueArray { 
    print(key, value) 
} 
+2

Это потрясающий однострочный. –

+0

Спасибо, отличный ответ –

+0

@ChrisKoknat спасибо –

2

Попробуйте это:

let dict = ["foo" : 1, "bar" : 1, "baz" : 2, "qux" : 2] 

let result = dict.map { (key: $0.0, value: $0.1) } 
       .sort { 
        if $0.value != $1.value { 
         return $0.value > $1.value 
        } 
        return $0.key < $1.key 
        } 

for r in result { 
    print("\(r.key) \(r.value)") 
} 

map превращает словарь в массив кортежей (key: "foo", value: 1) и т.д. Это затем становится вопросом сортировки этого массива с sort.

+0

Не нужно использовать карту. Вы можете сделать это, применив сортировку непосредственно к вашему словарю. –

+1

Да, вы правы. Но я предпочитаю, чтобы мои структуры данных имели собственные имена, а не ссылались на них по их позиционной ценности. Следовательно, "карта" –

Смежные вопросы