やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#の概念 LINQ(グループ化)

 SQLでいうgroup by句。

成果物

情報源

コード

  1. 1つのプロパティ
  2. 文字列プロパティの1文字目
  3. 計算された数値の範囲
  4. bool述語またはその他の式
  5. 複合キー

1. 1つのプロパティ

class Human {
    public string Name { get; }
    public int Age { get; }
    public Human(string name, int age) => (Name, Age) = (name, age);
}
class Main {
    public void Run() {
        List<Human> humans = CreateHumans();
        Show(Query(humans));
    }
    private List<Human> CreateHumans() {
        return new List<Human> {
            new Human("A1", 0), new Human("B1", 1),
            new Human("A2", 2), new Human("B2", 3),
            new Human("A3", 4), new Human("B3", 5),
        };
    }
    private IEnumerable<IGrouping<char,Human>> Query(in List<Human> humans) {
        return from h in humans
               group h by h.Name[0];
    }
    private void Show(in IEnumerable<IGrouping<char,Human>> groups) {
        foreach (var g in groups) {
            Console.WriteLine($"Key={g.Key}");
            foreach (var v in g) {
                Console.WriteLine($"  Value=Name:{v.Name}, Age:{v.Age}");
            }
        }
    }
}
Key=A
  Value=Name:A, Age:0
  Value=Name:A, Age:2
  Value=Name:A, Age:4
Key=B
  Value=Name:B, Age:1
  Value=Name:B, Age:3
  Value=Name:B, Age:5

2. 文字列プロパティの1文字目

 グループキーをh.Name[0]に。IGroupingのキー型をcharに。

    private IEnumerable<IGrouping<char,Human>> Query(in List<Human> humans) {
        return from h in humans
               group h by h.Name[0];
    }
    private void Show(in IEnumerable<IGrouping<char,Human>> groups) {
Key=A
  Value=Name:A1, Age:0
  Value=Name:A2, Age:2
  Value=Name:A3, Age:4
Key=B
  Value=Name:B1, Age:1
  Value=Name:B2, Age:3
  Value=Name:B3, Age:5

3. 計算された数値の範囲

    private List<Human> CreateHumans() {
        return new List<Human> {
            new Human("A", 19), new Human("B", 32),
            new Human("C", 10), new Human("D", 36),
            new Human("E", 47), new Human("F", 58),
        };
    }
    private IEnumerable<IGrouping<int,Human>> Query(in List<Human> humans) {
        return from h in humans
               orderby h.Age
               let gen = (h.Age / 10) * 10
               group h by gen into g
               orderby g.Key
               select g;
    }
    private void Show(in IEnumerable<IGrouping<int,Human>> groups) {
        foreach (var g in groups) {
            Console.WriteLine($"{g.Key}代");
            foreach (var v in g) {
                Console.WriteLine($"  Name:{v.Name}, Age:{v.Age}");
            }
        }
    }
10代
  Name:C, Age:10
  Name:A, Age:19
30代
  Name:B, Age:32
  Name:D, Age:36
40代
  Name:E, Age:47
50代
  Name:F, Age:58

4. bool述語またはその他の式

 グループキーが式になり型はbool

    private IEnumerable<IGrouping<bool,Human>> Query(in List<Human> humans) {
        return from h in humans
               group h by 40 < h.Age into g
               select g;
    }
40歳以上?=False
  Name:A, Age:19
  Name:B, Age:32
  Name:C, Age:10
  Name:D, Age:36
40歳以上?=True
  Name:E, Age:47
  Name:F, Age:58

5. 複合キー

    private IEnumerable<IGrouping<dynamic,Human>> Query(in List<Human> humans) {
        return from h in humans
               group h by new { h.Age, h.Name } into g
               orderby g.Key.Age, g.Key.Name
               select g;
    }
    private void Show(in IEnumerable<IGrouping<dynamic,Human>> groups) {
        foreach (var g in groups) {
            Console.WriteLine($"Key={g.Key}");
            foreach (var v in g) {
                Console.WriteLine($"  Name:{v.Name}, Age:{v.Age}");
            }
        }
    }
Key={ Age = 10, Name = C }
  Name:C, Age:10
Key={ Age = 19, Name = A }
  Name:A, Age:19
Key={ Age = 32, Name = B }
  Name:B, Age:32
Key={ Age = 36, Name = D }
  Name:D, Age:36
Key={ Age = 47, Name = E }
  Name:E, Age:47
Key={ Age = 58, Name = F }
  Name:F, Age:58

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux