C#.NET:Linqで配列やリストを簡単に並べ替えor抽出

配列やリストの並べ替えや抽出はLinqを使えばお手軽に行えます。

使い方

from [変数名] in [対象のリスト]
where [抽出条件]
group [変数名] by [グループ条件] into [変数名]
orderby [並べ替え条件] [descending/ascending]
select [取得する項目]

例:並べ替え

using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// データ格納用
        /// </summary>
        private class CustomST
        {
            public int Para1 { get; set; }
            public string Para2 { get; set; }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            // 並べ替え
            string[] ary = (from st in GetTestData()
                                      orderby st.Para1 descending, st.Para2 descending
                                      select string.Format("{0}:{1}", st.Para1, st.Para2)).ToArray();
            MessageBox.Show(string.Join("\n", ary));
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = "い" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "あ" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "う" });
            return list;
        }
    }
}

並べ替え②

string[] ary = (from st in GetTestData()
                          orderby st.Para1 descending, st.Para2 descending
                          select string.Format("{0}:{1}", st.Para1, st.Para2)).ToArray();
OrderByDescending、ThenByDescendingメソッドとラムダ式を使って下記のようにも書けます。
string[] ary = GetTestData().OrderByDescending(st => st.Para1)
                .ThenByDescending(st => st.Para2)
                .Select(st => string.Format("{0}:{1}", st.Para1, st.Para2))
                .ToArray();

抽出

string[] ary = (from st in GetTestData()
                          where st.Para1 == 1
                          select string.Format("{0}:{1}", st.Para1, st.Para2)).ToArray();
Whereメソッドとラムダ式を使って下記のようにも書けます。
string[] ary = GetTestData().Where(st => st.Para1 == 1)
                .Select(st => string.Format("{0}:{1}", st.Para1, st.Para2))
                .ToArray();

group by

string[] ary = (from st1 in GetTestData()
                          group st1 by st1.Para1 into g
                          select (from st2 in g
                                  orderby st2.Para2
                                  select string.Format("{0}:{1}", st2.Para1, st2.Para2)).First())
                          .ToArray();
GroupByメソッドとラムダ式を使って下記のようにも書けます。
string[] ary = GetTestData().GroupBy(st => st.Para1)
                .Select(g => g.OrderBy(st => st.Para2).First())
                .Select(st => string.Format("{0}:{1}", st.Para1, st.Para2))
                .ToArray();

複数の条件でgroupby

string[] ary = GetTestData().GroupBy(st => new { st.Para1, st.Para2 })
    .Select(g => g.OrderBy(st => st.Para2).First())
    .Select(st => string.Format("{0}:{1}", st.Para1, st.Para2))
    .ToArray();

SelectMany

IEnumerable<T>に対して、GroupByを行うとIEnumerableの入れ子IEnumerable<IEnumerable<T>>の状態になります。
この入れ子の中から必要なレコードを取り出して、IEnumerable<T>の型に格納したりするときなどに使用します。

using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// データ格納用
        /// </summary>
        private class CustomST
        {
            public int Para1 { get; set; }
            public int Para2 { get; set; }
            public string Para3 { get; set; }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            string[] ary = GetTestData().GroupBy(st => st.Para1)
                            .SelectMany(g => g.Where(st1 => st1.Para2 == g.Max(st2 => st2.Para2)).ToList())
                            .Select(st => string.Format("{0}:{1}:{2}", st.Para1, st.Para2, st.Para3))
                            .ToArray();
            MessageBox.Show(string.Join("\n", ary));
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = 1, Para3 = "あ" });
            list.Add(new CustomST() { Para1 = 3, Para2 = 2, Para3 = "い" });
            list.Add(new CustomST() { Para1 = 3, Para2 = 2, Para3 = "う" });
            list.Add(new CustomST() { Para1 = 3, Para2 = 1, Para3 = "え" });
            return list;
        }
    }
}

Take

先頭N件だけを取得したい時に使用します。
SqlのTopの機能です。

string[] ary = GetTestData().OrderBy(st => st.Para1)
    .Take(2)
    .Select(st => string.Format("{0}:{1}", st.Para1, st.Para2))
    .ToArray();

Max

int maxValue = GetTestData().Max(st => st.Para1)

Sum

int sumValue = GetTestData().Sum(st => st.Para1);

INNER JOIN


Table1
Para1 Para2
1
3
4
INNER JOIN
Table2
Para1 Para2
1 A
3 B
ON Table1.Para1 = Table2.Para1
Table1 Table2
Para1 Para2 Para1 Para2
1 1 A
3 3 B

using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// データ格納用
        /// </summary>
        private class CustomST
        {
            public int Para1 { get; set; }
            public string Para2 { get; set; }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            // INNER JOIN
            string[] ary = (from st1 in GetTestData()
                                      join st2 in GetTestData2()
                                      on st1.Para1 equals st2.Para1
                                      select string.Format("{0}:{1}:{2}", st1.Para1, st1.Para2, st2.Para2))
                                      .ToArray();
            MessageBox.Show(string.Join("\n", ary));
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = "い" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "あ" });
            list.Add(new CustomST() { Para1 = 4, Para2 = "う" });
            return list;
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData2()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = "A" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "B" });
            return list;
        }
    }
}

string[] ary = GetTestData().Join(GetTestData2(),
                            st1 => st1.Para1,
                            st2 => st2.Para1,
                            (st1, st2) => new
                            {
                                Para1 = st1.Para1,
                                Para2 = st1.Para2,
                                Para3 = st2.Para2
                            })
                            .Select(st => string.Format("{0}:{1}:{2}", st.Para1, st.Para2, st.Para3))
                            .ToArray();

GROUP JOIN


Table1
Para1 Para2
1
3
4
GROUP JOIN
Table2
Para1 Para2
1 A
3 B
3 C
ON Table1.Para1 = Table2.Para1
Table1 Table2
Para1 Para2 Para1 Para2
1 1 A
3 3 B
3 C
4 NULL NULL

using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// データ格納用
        /// </summary>
        private class CustomST
        {
            public int Para1 { get; set; }
            public string Para2 { get; set; }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            // GROUP JOIN
            string[] ary = (from st1 in GetTestData()
                                      join st2 in GetTestData2()
                                      on st1.Para1 equals st2.Para1 into g
                                      select string.Format("{0}:{1}:{2}",
                                          st1.Para1,
                                          st1.Para2,
                                          string.Join(",",
                                            (from st3 in g
                                             select st3.Para2)
                                             .ToArray())))
                                      .ToArray();
            MessageBox.Show(string.Join("\n", ary));
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = "い" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "あ" });
            list.Add(new CustomST() { Para1 = 4, Para2 = "う" });
            return list;
        }

        /// <summary>
        /// テストデータ作成
        /// </summary>
        /// <returns>テストデータ</returns>
        private List<CustomST> GetTestData2()
        {
            List<CustomST> list = new List<CustomST>();
            list.Add(new CustomST() { Para1 = 1, Para2 = "A" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "B" });
            list.Add(new CustomST() { Para1 = 3, Para2 = "C" });
            return list;
        }
    }
}

string[] ary = GetTestData().GroupJoin(GetTestData2(),
                            st1 => st1.Para1,
                            st2 => st2.Para1,
                            (st1, g) => new
                            {
                                Para1 = st1.Para1,
                                Para2 = st1.Para2,
                                Para3 = string.Join(",", g.Select(st3 => st3.Para2).ToArray())
                            })
                            .Select(st => string.Format("{0}:{1}:{2}", st.Para1, st.Para2, st.Para3))
                            .ToArray();
最終更新:2014年02月27日 01:14
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。