LoginSignup
6
3

More than 5 years have passed since last update.

【C#】yield returnを使って一つのエンティティを複数のエンティティに分割する

Posted at

やりたいこと

 やりたいことを表すいい名前が分からなかったので「一つのエンティティを複数のエンティティに分割する」とタイトルに書いてありますが、具体的には下表の"分割前"から"分割後"を作るメソッドを書きたいと思います。

・分割前

ID Fruit1 Price1 Fruit2 Price2 Fruit3 Price3
1 りんご 150 ぶんたん 200 めろん 2000
2 みかん 50 ぶどう 300 なし 130
3 はっさく 100 いちご 400 ざくろ 500

 
・分割後

Sequence Fruit Price
1 りんご 150
2 みかん 50
3 はっさく 100
4 ぶんたん 200
5 ぶどう 300
6 いちご 400
7 めろん 2000
8 なし 130
9 ざくろ 500

 "分割前"表は1行に果物の情報が3つ並んでいます。"分割後"表では1行に一つの果物を持つようになっています。シチュエーションとして、一行に複数項目あるデータでは処理を行いづらくなったためデータの変換をおこなうことを想定しています。

データ構造

 C#上でのデータの持ち方ですが、"分割前""分割後"のデータそれぞれは下記クラスをリストで持つようにしています。

// 分割前のデータ1行が入る
public class InputRecord
{
    public int ID { get; set; }
    public string Fruit1 { get; set; }
    public int Price1 { get; set; }
    public string Fruit2 { get; set; }
    public int Price2 { get; set; }
    public string Fruit3 { get; set; }
    public int Price3 { get; set; }
}

// 分割後のデータ1行が入る
public class OutputRecord
{
    public int Sequence { get; set; }
    public string Fruit { get; set; }
    public int Price { get; set; }
}

分割を行なうメソッド

private static IEnumerable<OutputRecord> ConvertToOutput(List<InputRecord> input)
{
    var seq = 0;

    foreach(var record in input)
    {
        // Fruit1
        seq++;
        yield return new OutputRecord
        {
            Sequence = seq,
            Fruit = record.Fruit1,
            Price = record.Price1,
        };

        // Fruit2
        seq++;
        yield return new OutputRecord
        {
            Sequence = seq,
            Fruit = record.Fruit2,
            Price = record.Price2,
        };


        // Fruit3
        seq++;
        yield return new OutputRecord
        {
            Sequence = seq,
            Fruit = record.Fruit3,
            Price = record.Price3,
        };
    }
}

 1行を3分割することを考えるとこのようなメソッドが出来上がります。foreachでループして、一行ごとにyield returnを3回行っているだけですね。

メソッド呼び出し部

static void Main(string[] args)
{
    // テストデータ(分割前表と同じ内容)
    var input = new List<InputRecord>
    {
        new InputRecord
        {
            ID = 1,
            Fruit1 = "りんご",
            Price1 = 150,
            Fruit2 = "みかん",
            Price2 = 50,
            Fruit3 = "はっさく",
            Price3 = 100,
        },
        new InputRecord
        {
            ID = 2,
            Fruit1 = "ぶんたん",
            Price1 = 200,
            Fruit2 = "ぶどう",
            Price2 = 300,
            Fruit3 = "いちご",
            Price3 = 400,
        },
        new InputRecord
        {
            ID = 3,
            Fruit1 = "めろん",
            Price1 = 2000,
            Fruit2 = "なし",
            Price2 = 130,
            Fruit3 = "ざくろ",
            Price3 = 500,
        },
    };

    // メソッド呼び出し
    List<OutputRecord> output = ConvertToOutput(input).ToList();
}

 テスト用の入力データ作成とメソッド呼び出しを行なうとこのようになります。

考察

メリット
・List<>クラスのAddメソッドを書かなくてすむ

デメリット
・yield句に慣れていないと処理の流れを見失う

6
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3