配列を利用する(構造体型、ソート)

本記事では構造体型を要素とする配列を使うサンプルを示します。下記のような構造体を定義します。名前 (String型) と、生誕年 (Int型) をメンバとします。

struct NameAndYearOfBirth{
    var Name: String
    var YearOfBirth: Int
}

起動時に構造体の配列に要素として人の名前と生誕日を設定します。要素に同姓同名の Bill Evans さんが入っていることにご注目ください。ちなみに1929年生まれのほうはピアニストで、1958年生まれのほうはサクソフォニストです。

Fig. 1 名前が昇順で生誕年も昇順
Fig. 2 名前が昇順で生誕年は降順
Fig. 3 名前が降順で生誕年は昇順
Fig. 4 名前が降順で生誕年も降順

配列の要素を構造体のメンバを考慮しつつソートするには下記のコードを使います。$0 と $1 の並び方と大小関係で脳がパニックを起こしますが、がんばって指定してください(笑)。

// 名前をAからZにソートしつつ、誕生年を小から大にソートする.
Data001 = Data000.sorted( by: {
                ( $0.Name, $0.YearOfBirth ) < ( $1.Name, $1.YearOfBirth )
            })

// 名前をAからZにソートしつつ、誕生年を大から小にソートする.
Data001 = Data000.sorted( by: {
                ( $0.Name, $1.YearOfBirth ) < ( $1.Name, $0.YearOfBirth )
            })

// 名前をZからAにソートしつつ、誕生年を小から大にソートする.
Data001 = Data000.sorted( by: {
                ( $0.Name, $1.YearOfBirth ) > ( $1.Name, $0.YearOfBirth )
            })

// 名前をZからAにソートしつつ、誕生年を大から小にソートする.
Data001 = Data000.sorted( by: {
                ( $0.Name, $0.YearOfBirth ) > ( $1.Name, $1.YearOfBirth )
            })

では、以上をふまえて実際のコードを簡単に説明します。

3 〜 6行目で構造体の定義をしています。
15、16行目で配列の宣言をしています。Data000がオリジナルデータ、Data001がソートされたデータ.
189行目で初期データを仕込みます。Data000 しかデータを仕込んでいないことに注目のこと。
122、137、152、167行目で複合条件のソートをかけています。sorted() を使って戻り値でデータのコピーを取得していることに注目のこと
32 〜 42行目でオリジナルデータ配列の要素数ぶんループさせて、その内容を表示しています。
53 〜 63行目でソートされたデータ配列の要素数ぶんループさせて、その内容を表示しています。

import SwiftUI

struct NameAndYearOfBirth{
    var Name: String
    var YearOfBirth: Int
}

struct ContentView: View {

    // テキストとボタンの表示文字列の大きさ.
    let POINT_SIZE_TEXT = 16.0
    let POINT_SIZE_BUTTON = 12.0

    // 配列を宣言する.
    @State var Data000 = [NameAndYearOfBirth]()
    @State var Data001 = [NameAndYearOfBirth]()

    var body: some View {


        VStack {

            Spacer()

            // 見出し.
            Text( "original" )
                .foregroundColor( .pink )
                .font( .system( size: POINT_SIZE_TEXT ) )
                .frame( maxWidth: .infinity, alignment: .leading )

            // データの要素個数ぶんループしてオリジナルデータを表示する.
            ForEach ( 0 ..< Data000.count, id: \.self ) { n in

                let s = Data000[n].Name
                let v = Data000[n].YearOfBirth

                let str = String( format: "[%d]: %@, %d", n, s, v )
                Text( str )
                    .font( .system( size: POINT_SIZE_TEXT ) )
                    .frame( maxWidth: .infinity, alignment: .leading )

            }

            Spacer()

            // 見出し.
            Text( "sorted" )
                .foregroundColor( .pink )
                .font( .system( size: POINT_SIZE_TEXT ) )
                .frame( maxWidth: .infinity, alignment: .leading )

            // データの要素個数ぶんループしてソートされたデータを表示する.
            ForEach ( 0 ..< Data001.count, id: \.self ) { n in

                let s = Data001[n].Name
                let v = Data001[n].YearOfBirth

                let str = String( format: "[%d]: %@, %d", n, s, v )
                Text( str )
                    .font( .system( size: POINT_SIZE_TEXT ) )
                    .frame( maxWidth: .infinity, alignment: .leading )

            }

            Spacer()

            VStack {

                HStack {

                    // AからZにソートするボタン.
                    Button( action: {
                        Data001 = Data000.sorted( by: { $0.Name < $1.Name } )
                    }){
                        Text( "Sort\nA to Z" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // ZからAにソートするボタン.
                    Button( action: {
                        Data001 = Data000.sorted( by: { $0.Name > $1.Name } )
                    }){
                        Text( "Sort\nZ to A" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // 数字を小から大にソートするボタン.
                    Button( action: {
                        Data001 = Data000.sorted( by: { $0.YearOfBirth < $1.YearOfBirth } )
                    }){
                        Text( "Sort\n0 to 999" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // 数字を大から小にソートするボタン.
                    Button( action: {
                        Data001 = Data000.sorted( by: { $0.YearOfBirth > $1.YearOfBirth } )
                    }){
                        Text( "Sort\n999 to 0" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                }

                HStack {

                    // AからZにソートしつつ小から大にソートするボタン.
                    Button( action: {

                        Data001 = Data000.sorted( by: {
                                        ( $0.Name, $0.YearOfBirth ) < ( $1.Name, $1.YearOfBirth )
                                    })

                    }){
                        Text( "Sort\nA to Z\n0 to 999" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // AからZにソートしつつ大から小にソートするボタン.
                    Button( action: {

                        Data001 = Data000.sorted( by: {
                                        ( $0.Name, $1.YearOfBirth ) < ( $1.Name, $0.YearOfBirth )
                                    })

                    }){
                        Text( "Sort\nA to Z\n999 to 0" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // ZからAにソートしつつ小から大にソートするボタン.
                    Button( action: {

                        Data001 = Data000.sorted( by: {
                                        ( $0.Name, $1.YearOfBirth ) > ( $1.Name, $0.YearOfBirth )
                                    })

                    }){
                        Text( "Sort\nZ to A\n0 to 999" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                    // ZからAにソートしつつ大から小にソートするボタン.
                    Button( action: {

                        Data001 = Data000.sorted( by: {
                                        ( $0.Name, $0.YearOfBirth ) > ( $1.Name, $1.YearOfBirth )
                                    })

                    }){
                        Text( "Sort\nZ to A\n999 to 0" )
                            .font( .system( size: POINT_SIZE_BUTTON ) )
                            .foregroundColor( .white )
                    }
                    .padding()
                    .background( .blue )

                }

            }

            Spacer()

        }
        .onAppear()
        {
            // データをしこむ.
            SetInitialData( &Data000 )
        }


    }

}

func SetInitialData( _ data: inout [NameAndYearOfBirth] ) -> Void {

    data.removeAll()

    data.append( NameAndYearOfBirth( Name: "Art Pepper",      YearOfBirth: 1925 ))
    data.append( NameAndYearOfBirth( Name: "Bill Evans",      YearOfBirth: 1929 )) // same name, piano.
    data.append( NameAndYearOfBirth( Name: "Bill Evans",      YearOfBirth: 1958 )) // same name, saxphone.
    data.append( NameAndYearOfBirth( Name: "Charles Mingus",  YearOfBirth: 1922 ))
    data.append( NameAndYearOfBirth( Name: "Dexter Gordon",   YearOfBirth: 1923 ))
    data.append( NameAndYearOfBirth( Name: "Eric Dolphy",     YearOfBirth: 1928 ))
    data.append( NameAndYearOfBirth( Name: "Freddie Hubbard", YearOfBirth: 1938 ))
    data.append( NameAndYearOfBirth( Name: "Gil Evans",       YearOfBirth: 1912 ))
    data.append( NameAndYearOfBirth( Name: "Hank Mobley",     YearOfBirth: 1930 ))
    data.append( NameAndYearOfBirth( Name: "Ike Quebec",      YearOfBirth: 1918 ))
    data.append( NameAndYearOfBirth( Name: "John Coltrane",   YearOfBirth: 1926 ))

    return

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}