【プログラミング初心者】Swift練習問題~ソート~回答例

#ソート
##回答例

```swift
func sort(list: [Int]) -> [Int] {
    var sortedList = list
    
    for currentIndex in 0..<sortedList.count {
        for sortIndex in (currentIndex + 1)..<sortedList.count {
            if sortedList[currentIndex] < sortedList[sortIndex] {
                let tmp = sortedList[currentIndex]
                sortedList[currentIndex] = sortedList[sortIndex]
                sortedList[sortIndex] = tmp
            }
        }
    }
    
    return sortedList
}
```
##解説
降順ソートなので配列の0番から順に大きい値が格納されるように実装します。
###ソートの考え方
この実装は**バブルソート**と呼ばれ、ソートにおいて最も基本となる考え方です。

`[10, 11, 5, 15, 9, 2, 5]`という配列を例にとって考え方を図で解説します。

最初の配列のイメージは以下の通りです。
<img width="576" alt="ソート１.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/bb167911-0ffb-2b3d-ccb9-683955efe7f2.png">
まず0番の配列に注目していきます。

はじめに0番と1番の値を比較します。
比較した結果`10 < 11`となるので0番と1番の値を入れ替え、大きい値を0番に格納します。
<img width="577" alt="ソート２.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/65637296-f681-97c5-bd64-ecf46fd9b7c4.png">
次は0番と2番の値を比較します。
`11 > 5`となるので入れ替えは発生しません。
<img width="577" alt="ソート３.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/825f3cf8-ba9b-c038-f9b0-9bdf71040277.png">
その後0番と3~6番までの値を比較していき大きい方ければ0番の値と入れ替えます。
その結果配列は以下の状態になります。
<img width="576" alt="ソート４.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/e15e0847-641a-98ae-e786-b19d3fcb3285.png">
入れ替えが終わった結果0~6番の中で最大の値が0番に格納されています。

次は1番の配列に注目します。

先の処理で0番が最大値ということは確定しているため1番と2番から比較していきます。
`10 > 5`なのでここは入れ替えません。
<img width="577" alt="ソート５.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/2df2169b-13f6-6bbe-51e1-c5d8c8f533f7.png">
1番と3番を比較します。
`10 < 11`なので1番と3番の値を入れ替えます。
<img width="577" alt="ソート６.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/a654e897-0818-1369-278b-9183261ed5da.png">
ここからもやはり同様に1番と残りの4~6番まで比較していきます。
その結果、1~6番の中で最大値が1番として格納されることになります。

ここからまた注目する配列番号を2、3...とずらし、同じ操作を行っていくことで最終的に大きい順に並べ替えることができます。
<img width="576" alt="ソート７.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326173/8c04fd69-e450-4da8-20b1-78ba2b9437af.png">
このように大きいものが泡のように上に上がってくるという意味でこのソート方法は「バブルソート」と呼ばれています。

###実装
後はソートの考え方で解説した方法に沿って実装するだけです。

外側のループで注目する要素番号をずらし、配列の数だけループを回します。
`currentIndex`が注目する要素番号になります。

内側のループで`currentIndex`に格納されている値と比較します。
`sortIndex`が比較対象の要素番号です。
先程説明した通り比較対象の要素番号は`currentIndex`の次から始まるので
`(currentIndex + 1)..<sortedList.count`としています。
※ 効率が悪くなりますが`0..<sortedList.count`としてループを回しても結果は変わりません。

`if`で値を比較し大きければ値を入れ替えています。
入れ替え処理は以下のようにしています。

```swift
let tmp = sortedList[currentIndex]
sortedList[currentIndex] = sortedList[sortIndex]
sortedList[sortIndex] = tmp
```
`tmp`という変数に`sortedList[currentIndex]`を格納しています。

直観的に

```swift
sortedList[currentIndex] = sortedList[sortIndex]
sortedList[sortIndex] = sortedList[currentIndex]
```
としてしまいたいところかも知れませんが、このようにするとはじめの`sortedList[currentIndex] = sortedList[sortIndex]`で`sortedList[currentIndex]`の値が書き換わっています。
そのため`sortedList[sortIndex] = sortedList[currentIndex]`では書き換わった後の値を代入していることになり、`sortedList[currentIndex]`と`sortedList[sortIndex]`は同じ値になってしまいます。

これを防ぐために一時的に値を格納する用の変数として`tmp`を作り、値を入れ替えています。

あとはループが最後まで回ればソートが完了します。

ソートが完了したらあとは戻り値として`sortedList`をreturnしてあげれば処理完了となります。