C# - よく使うクラス - List - ソート

 クラウディア
1. 概要
2. 自身を単純ソート
3. ソートして別のリストへ

1. 概要

 複数の要素が存在するならば、並べたくなるのが、人情ってもんです。  そのせいか、ソートの手法には、複数の方法があるようです。  本ページは、下記のサイトを参考にさせていただきました。
C# リストで複数キーを指定したソート方法

2. 自身を単純ソート

 ソートに使用する要素が一つであり、自身をソートする場合は

List.Sort((要素1, 要素2) => 要素1 と 要素2 を比較する演算);
 と書きます。  「要素1 と 要素2 を比較する演算」は、結果が、正数にならなければなりません。  なので、「int」であれば、減算で十分ですが、「double」であれば「Math.Sign()」を使わなければならないし、「string」であれば、「string.Compare()」を使うなどの工夫が必要になります。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class TestConTains
{
	[Serializable]
	public class myClass
	{
		public int		i	= 0;												// 数値型要素
		public string	s	= String.Empty;										// 文字列型要素
	}

	static public void Main ()
	{
		List<myClass> list = new List<myClass>
			{
				new myClass { i = 2, s = "Y" },
				new myClass { i = 1, s = "Z" },
				new myClass { i = 3, s = "X" },
			};

		list.Sort((a, b) => a.i - b.i);

		foreach (myClass item in list)
		{
	        Console.WriteLine("["+ item.i +"] ["+ item.s +"]");
		}

        Console.WriteLine("");

		list.Sort((a, b) => string.Compare(a.s, b.s));

		foreach (myClass item in list)
		{
	        Console.WriteLine("["+ item.i +"] ["+ item.s +"]");
		}

        Console.WriteLine("");
		list.Sort((a, b) => a.i - b.i);

		myClass first = list.First();
		myClass last  = list.Last();

        Console.WriteLine("first ["+ first.i +"] ["+ first.s +"]");
        Console.WriteLine("last  ["+ last.i +"] ["+ last.s +"]");
	}
}
 てなソースを書いて、コンパイル後、実行すると下記の結果が得られます。

[1] [Z]
[2] [Y]
[3] [X]

[3] [X]
[2] [Y]
[1] [Z]

first [1] [Z]
last  [3] [X]
 尚、43、44行目の「First」「Last」を使うために、4行目の「using System.Linq;」は必要です。  ソートする要素が、複数存在する場合は、別途、比較メソッドが必要なのですが、書く機会があれば、そのうち書きます。

3. ソートして別のリストへ

 「OrderBy」に代表されるメソッドを使用して、「List」をソートしたものを「IOrderedEnumerable」で定義する別のリストへ移すことができます。  参考サイトに、「遅延実行されるため、戻り値に対して「foreach」等で列挙操作を行うまではソートされない」と書いてあるのが、いささ気になりますが。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class MyMain
{
	[Serializable]
	public class myClass
	{
		public int		i	= 0;												// 数値型要素
		public string	s	= String.Empty;										// 文字列型要素
	}

	static public void Main ()
	{
		List<myClass> list = new List<myClass>
			{
				new myClass { i = 2, s = "Y" },
				new myClass { i = 1, s = "Z" },
				new myClass { i = 3, s = "X" },
				new myClass { i = 5, s = "Y" },
				new myClass { i = 2, s = "X" },
				new myClass { i = 2, s = "Z" },
			};

		IOrderedEnumerable<myClass> list01 = list.OrderBy(x => x.i).ThenBy(x => x.s);

		foreach (myClass item in list01)
		{
	        Console.WriteLine("["+ item.i +"] ["+ item.s +"]");
		}

        Console.WriteLine("");
		IOrderedEnumerable<myClass> list02 = list.OrderByDescending(x => x.s).ThenByDescending(x => x.i);

		foreach (myClass item in list02)
		{
	        Console.WriteLine("["+ item.s +"] ["+ item.i +"]");
		}
	}
}
 てなソースを書いて、コンパイル後、実行すると下記の結果が得られます。

[1] [Z]
[2] [X]
[2] [Y]
[2] [Z]
[3] [X]
[5] [Y]

[Z] [2]
[Z] [1]
[Y] [5]
[Y] [2]
[X] [3]
[X] [2]
 最初に、数値昇順、文字昇順でソートした結果、次に、文字降順、数値降順でソートした結果を出力しています。  「OrderBy」で最優先するもの、「ThenOrderby」で以降の要素の比較をつなげています。  「...Descending」が、降順になります。  これらのメソッドを、参考サイトのまるパクリで説明しておくと。
 メソッド   意味   備考 
OrderBy 第一優先の要素を昇順ソート
OrderByDescending 第一優先の要素を降順ソート
ThenBy 第二優先以降の要素を昇順ソート
ThenByDescending 第二優先以降の要素を降順ソート

 てなことになります。
 この場合、「string」もうまいことソートされているのでありがたい。


AbemaTV 無料体験