【Swift】多次元配列を昇順でソート

どうも、ねこきち(@nekokichi1_yos2)です。

 

Int型の多次元配列をソートする方法が載ってなかったので、備忘録として記載。

 

バブルソート、というアルゴリズムを使うと、簡単に実装できました。

 

今回のバブルソートを実装する際、下記を参考にさせていただきました。

donguriさん、ありがとうございました。

note.com

 

 

解説

 

今回使用する配列は、Int型の2次元配列です。

var array = [[2020,9,5],[2020,12,5],[2019,11,9],[2019,11,1],[2019,1,13],[2010,5,13],[2020,2,20],[2010,6,8]]

([年、月、日]の配列)

 

仕組みは、

  • 隣り合う要素を比較
  • 大小関係が成り立つかを調べる
  • 成り立てば両方を入れ替える
  • 1周して1度も成り立たなくなれば、終了

です。

 

repeat-while文は、条件式(flag)が

  • trueなら継続
  • falseなら抜ける

で、ループ度に条件式はfalseにリセットされ、入れ替えが起こればtrueになるのでまた1つ目の要素から大小関係の照合が行われ、1周ループしてfalseのままなら抜けます。

 

strideは、指定範囲(from~to)を指定数字刻み(by)でループするもので、今回の場合、

  • 1,2,3,4,5,6,7

の数字がiに返されます。

(指定範囲の末尾は、to - 1、で、最後の数字は含まれません。)

 

swapAtは、引数に指定した配列内にある2つの要素を入れ替えます。

 

年のソート

 

stirdeにより、for文のiには1~7が入り、

  • i番目
  • i-1番目

の2つを比較します。

 

最初は0番目と1番目を比較し、最後は6番目と7番目を比較。

 

これで、年の昇順ソートが完成。

 

月のソート

 

もし月のソートだけ行えば、月を基準にソートされるので、年の昇順が崩れてしまいます。

 

ですから、年の順番を保ちつつ、月をソートする場合、年の条件式も加える必要があります。

 

既に年は昇順に並んでるので、後は比較対象である2つの要素が同じ年?、であるかを確認するだけです。

 

日のソート

 

既に年と月の昇順は成り立ってるので、比較対象が同じ年/月であるかを確かめればOKです。

 

ソースコード

 

//ループ判定
var flag = false
var array = [[2020,9,5],[2020,12,5],[2019,11,9],[2019,11,1],[2019,1,13],[2010,5,13],[2020,2,20],[2010,6,8]]

//年をソート
func sortYear() {
    repeat {
        flag = false
        for i in stride(from: 1, to: array.count, by: 1) {
            if array[i][0] < array[i-1][0] {
                array.swapAt((i-1), i)
                flag = true
            }
        }
    } while flag
}

//月をソート
func sortMonth() {
    repeat {
        flag = false
        for i in stride(from: 1, to: array.count, by: 1) {
            if array[i][0] == array[i-1][0] {
                if array[i][1] < array[i-1][1] {
                    array.swapAt((i-1), i)
                    flag = true
                }
            }
        }
    } while flag
}

//日をソート
func sortDay() {
    repeat {
        flag = false
        for i in stride(from: 1, to: array.count, by: 1) {
            if array[i][0] == array[i-1][0] {
                if array[i][1] == array[i-1][1] {
                    if array[i][2] < array[i-1][2] {
                        array.swapAt((i-1), i)
                        flag = true
                    }
                }
            }
        }
    } while flag
}

 

結果

 

//年のソート
[[2010, 5, 13], [2010, 6, 8], [2019, 11, 9], [2019, 11, 1], [2019, 1, 13], [2020, 9, 5], [2020, 12, 5], [2020, 2, 20]]
//年、月のソート
[[2010, 5, 13], [2010, 6, 8], [2019, 1, 13], [2019, 11, 9], [2019, 11, 1], [2020, 2, 20], [2020, 9, 5], [2020, 12, 5]]
//年、月、日のソート
[[2010, 5, 13], [2010, 6, 8], [2019, 1, 13], [2019, 11, 1], [2019, 11, 9], [2020, 2, 20], [2020, 9, 5], [2020, 12, 5]]