いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Linq入門記-06 (クエリキーワード, クエリ構文, ソート, 並び替え, orderby, ascending, descending)


今回は、ソートです。
Linqで、ソートを行うにはSQLでもおなじみのorder byを利用します。


以下のように記述します。

orderby ソート条件となる値 {ascending | descending}


order byではなく、orderbyである事に注意です。
また、ascendingは省略可能となります。


SQLでのORDER BYと同じく一度に複数の条件にてソートも行えます。

orderby x.Id ascending, x.Name ascending, x.Age descending

上記の場合は、Id,Nameの昇順で、Ageの降順となります。


尚、fromキーワードなどと同じくorderbyも複数記述できます。

orderby x.Id ascending
orderby x.Name ascending
orderby x.Age desceding

上記の場合、記述的には

orderby x.Id ascending, x.Name ascending, x.Age descending

を3行に分割したように見えて、同じ結果になると思いますが
結果は異なりますので注意が必要です。


なぜなら、

orderby x.Id ascending, x.Name ascending, x.Age descending

の場合は、一度で上記の条件にてソート処理が行われますが

orderby x.Id ascending
orderby x.Name ascending
orderby x.Age desceding

の場合は、順にソート処理が行われます。
なので、最終的な結果はx.Ageの降順となります。


複数のorderbyを記述するのは、間にwhere等を組み合わせて
順に結果を構築する際などに利用したりします。


以下、サンプルです。

#region LinqSamples-06
    public static class StringExtensions {

        public static int ToInt(this string self) {
            return int.Parse(self);
        }
    }

    public class LinqSamples06 : IExecutable {

        enum Country {
             Japan
            ,America
            ,China
        }

        class Person {
            public string Id{ get; set; }
            public string Name{ get; set; }
            public AddressInfo Address{ get; set;}
            public Country Country{ get; set; }
        }

        class AddressInfo {
            public string   PostCode{ get; set; }
            public string   Prefecture{ get; set; }
            public string   Municipality{ get; set; }
            public string   HouseNumber{ get; set; }
            public string[] Tel{ get; set; }
            public string[] Frends{ get; set; }
        }


        IEnumerable<Person> CreateSampleData() {

            return new Person[]{
                 new Person{ 
                         Id="00001"
                        ,Name="gsf_zero1"
                        ,Address=new AddressInfo{
                                         PostCode="999-8888"
                                        ,Prefecture="東京都"
                                        ,Municipality="どこか1"
                                        ,HouseNumber="番地1"
                                        ,Tel=new []{"090-xxxx-xxxx"}
                                        ,Frends=new string[]{}
                        }
                        ,Country=Country.Japan
                 }
                ,new Person{ 
                         Id="00002"
                        ,Name="gsf_zero2"
                        ,Address=new AddressInfo{
                                         PostCode="888-7777"
                                        ,Prefecture="京都府"
                                        ,Municipality="どこか2"
                                        ,HouseNumber="番地2"
                                        ,Tel=new []{"080-xxxx-xxxx"}
                                        ,Frends=new []{"00001"}
                        }
                        ,Country=Country.Japan
                }
                ,new Person{ 
                         Id="00003"
                        ,Name="gsf_zero3"
                        ,Address=new AddressInfo{
                                         PostCode="777-6666"
                                        ,Prefecture="北海道"
                                        ,Municipality="どこか3"
                                        ,HouseNumber="番地3"
                                        ,Tel=new []{"070-xxxx-xxxx"}
                                        ,Frends=new []{"00001", "00002"}
                        }
                        ,Country=Country.America
                }
                ,new Person{ 
                         Id="00004"
                        ,Name="gsf_zero4"
                        ,Address=new AddressInfo{
                                         PostCode="777-6666"
                                        ,Prefecture="北海道"
                                        ,Municipality="どこか4"
                                        ,HouseNumber="番地4"
                                        ,Tel=new []{"060-xxxx-xxxx", "111-111-1111", "222-222-2222"}
                                        ,Frends=new []{"00001", "00003"}
                        }
                        ,Country=Country.America
                }
            };
        }

        public void Execute() {

            IEnumerable<Person> persons = CreateSampleData();

            // 
            //  昇順.
            //  (昇順の場合のascendingは付けても付けなくても良い)
            //
            var query1 = from    person in persons
                         orderby person.Id.ToInt() ascending
                         select  person;

            Console.WriteLine("============================================");
            foreach(Person person in query1) {
                Console.WriteLine("Id={0}, Name={1}", person.Id, person.Name);
            }

            //
            // 降順.
            //
            var query2 = from    person in persons
                         orderby person.Id.ToInt() descending
                         select  person;

            Console.WriteLine("============================================");
            foreach(Person person in query2) {
                Console.WriteLine("Id={0}, Name={1}", person.Id, person.Name);
            }

            //
            // 複数の条件でソート.
            //
            var query3 = from    person in persons
                         orderby person.Address.PostCode, person.Id.ToInt()
                         select  person;

            Console.WriteLine("============================================");
            foreach(Person person in query3) {
                Console.WriteLine("Id={0}, Name={1}", person.Id, person.Name);
            }

            //
            // 複数のorderby.
            // (query3の場合と結果が異なる事に注意)
            //
            // query3の場合は一度で2つの条件にてソート処理が行われるが
            // query4は、2回に分けてソート処理が行われる。
            //
            // つまり、orderby person.Address.PostCodeで一旦ソートが
            // 行われるが、その後orderby person.IdによってID順にソート
            // され直されてしまう。
            //
            var query4 = from    person in persons
                         orderby person.Address.PostCode
                         orderby person.Id.ToInt()
                         select  person;

            Console.WriteLine("============================================");
            foreach(Person person in query4) {
                Console.WriteLine("Id={0}, Name={1}", person.Id, person.Name);
            }
        }
    }
#endregion