# ranking list

{% tabs %}
{% tab title="1" %}
:point\_right: [replit](https://replit.com/@pegasusroe/ranking-list-2#main.swift)

```swift
// name and score
let dict = [                                // Dictionary<Key, Value>
    "Sam": 79, "Joe": 5, "Mary": 79,        // Key     = String
    "Tom": 5, "Alex": 82, "Nancy": 1        // Value   = Int
] 

// ⭐️ 1. sort it by value first
let sorted = dict.sorted { $0.value > $1.value }

var prev: Int?              // previous score
var currentRank = 0
var rankingList = [(name: String, score: Int, rank: Int)]()

// ⭐️ 2. give every element a rank
for (i, elem) in sorted.enumerated() {
    
    // if elem.value is not the same as previous score,
    // update previous score and current rank
    if prev == nil || elem.value != prev! {
        prev = elem.value
        currentRank = i + 1         // i is zero-based, rank is one-based
    }
    
    rankingList.append((elem.key, elem.value, currentRank))
}

print(rankingList)
/*
[
    (name: "Alex" , score: 82, rank: 1), 
    (name: "Sam"  , score: 79, rank: 2), 
    (name: "Mary" , score: 79, rank: 2),    // no 3rd place
    (name: "Joe"  , score:  5, rank: 4), 
    (name: "Tom"  , score:  5, rank: 4),    // no 5th place
    (name: "Nancy", score:  1, rank: 6)
]
*/
```
{% endtab %}

{% tab title="2" %}
:point\_right: [paiza.io](https://paiza.io/projects/sWfkiF5perWOpxMoeGHNyQ?language=swift)

```swift
let dict = [                                // Dictionary<Key, Value>
    "Sam": 79, "Joe": 5, "Mary": 18,        // Key     = String
    "Tom": 5, "Alex": 82, "Nancy": 1        // Value   = Int
]                                           // Element = (key: Key, value: Value)

// ⭐️ 按照「分數」分組
let dict2 = dict.grouped { $0.value }       // seq.grouped(by:) -> 👥 相關
/*
    ⭐️ seq.grouped(by:)
    --------------------------------------
    Sequence -> Dictionary<Key, [Element]>
    
    其中 Key 為參數 by: (Element) -> Key 所指定。
    
    [  Key  ╭─── Value = [Element] ───╮
        79: [(key: "Sam"  , value: 79)], 
         5: [(key: "Tom"  , value:  5) , (key: "Joe", value: 5)], 
        82: [(key: "Alex" , value: 82)], 
        18: [(key: "Mary" , value: 18)], 
         1: [(key: "Nancy", value:  1)]
    ]
*/

// ⭐️ 按照「分數」由大到小排列
let sorted = dict2.sorted { $0.key > $1.key }        
/*
    ⭐️ seq.sorted(by:) 
    ---------------------
    Sequence -> [Element]
    
    一個 Dictionary 的 Element = (key: Key, value: Value)，
    但現在的 Key = Int，Value = [(key: String, value: Int)]，
    所以經過 .sorted(by:) 之後自然會變成：
        [(key: Int, value: [(key: String, value: Int)])]
    
    [
        (key: 82, value: [(key: "Alex" , value: 82)]), 
        (key: 79, value: [(key: "Sam"  , value: 79)]), 
        (key: 18, value: [(key: "Mary" , value: 18)]), 
        (key:  5, value: [(key: "Tom"  , value:  5), (key: "Joe", value: 5)]), 
        (key:  1, value: [(key: "Nancy", value:  1)])
    ]
*/

// ⭐️ 幫 Sequence 編號
let enumerated = sorted.enumerated()
/*
    ⭐️ seq.enumerated()
    ------------------------------------------
    Sequence -> EnumeratedSequence<[Element]>
    
    幫 Sequence 編號，編號後可用下列語法來處理每個元素：
    for (i, elem) in seq.enumerated() { ... }
    
    所以在本例中，可以假想成經過 .enumerated() 處理後，變成這樣：
    [
        (0, (key: 82, value: [(key: "Alex" , value: 82)])), 
        (1, (key: 79, value: [(key: "Sam"  , value: 79)])), 
        (2, (key: 18, value: [(key: "Mary" , value: 18)])), 
        (3, (key:  5, value: [(key: "Tom"  , value:  5), (key: "Joe", value: 5)])), 
        (4, (key:  1, value: [(key: "Nancy", value:  1)]))
    ]
*/

// ⭐️ 將 elem 元素內部的值(elem.value)轉變為陣列，然後在用 .flatMap()
//   將所有陣列「壓成」一維陣列。
let ranking = enumerated.flatMap { (i, elem) in
    elem.value.map { (name: $0.key, rank: i + 1, value: $0.value) }
}

/*
[
    (name: "Alex" , rank: 1, value: 82), 
    (name: "Sam"  , rank: 2, value: 79), 
    (name: "Mary" , rank: 3, value: 18), 
    (name: "Tom"  , rank: 4, value:  5), 
    (name: "Joe"  , rank: 4, value:  5), 
    (name: "Nancy", rank: 5, value:  1)
]
*/
```
{% endtab %}

{% tab title="👥 相關" %}
* [seq.statemap-\_-\_](../../swift/collections/sequence/seq.statemap-_-_ "mention")
* [seq.grouped-by](../../swift/collections/sequence/seq.grouped-by "mention")
{% endtab %}

{% tab title="📘 手冊" %}
* [Swift](https://developer.apple.com/documentation/swift)
  * [Dictionary](https://developer.apple.com/documentation/swift/dictionary) ⟩ [.init(grouping:by:)](https://developer.apple.com/documentation/swift/dictionary/3127163-init)
  * [Sequence](https://developer.apple.com/documentation/swift/sequence) ⟩ [.enumerated()](https://developer.apple.com/documentation/swift/sequence/1641222-enumerated)
{% endtab %}

{% tab title="🗣 討論" %}
* [Swift ranking dictionary](https://stackoverflow.com/a/56513861/5409815) - build ranking list from scores
{% endtab %}
{% endtabs %}
