Enumerable.OrderBy メソッド
【C#】
シーケンスの要素をキーに従って昇順に並べ替えます。
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>
(this IEnumerable source, Func keySelector)
指定された比較子を使用してシーケンスの要素を昇順に並べ替えます。
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>:
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
【VB】
シーケンスの要素をキーに従って昇順に並べ替えます。
<ExtensionAttribute>
Public Shared Function OrderBy(Of TSource, TKey)
(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey))
As IOrderedEnumerable(Of TSource)
指定された比較子を使用してシーケンスの要素を昇順に並べ替えます。
<ExtensionAttribute>
Public Shared Function OrderBy(Of TSource, TKey)
(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey), comparer As IComparer(Of TKey))
As IOrderedEnumerable(Of TSource)
Enumerable.ThenBy メソッド
【C#】
キーに従って、シーケンス内の後続の要素を昇順で配置します。
ThenBy<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>)
指定された比較子を使用して、シーケンス内の後続の要素を昇順で配置します。
ThenBy<TSource, TKey>(IOrderedEnumerable<TSource>, Func<TSource, TKey>, IComparer<TKey>)
【VB】
キーに従って、シーケンス内の後続の要素を昇順で配置します。
ThenBy(Of TSource, TKey)(IOrderedEnumerable(Of TSource), Func(Of TSource, TKey))
指定された比較子を使用して、シーケンス内の後続の要素を昇順で配置します。
ThenBy(Of TSource, TKey)(IOrderedEnumerable(Of TSource), Func(Of TSource, TKey), IComparer(Of TKey))
簡単に言うと…
シーケンス(配列やコレクションなど)の各要素を昇順に並び替える。
データを並び替える項目が一つ目ならOrderByを使用しします。
二つ目からはThenByを使用します。
このメソッドは遅延実行されます。
テストデータです。
【C#】
private class Fruit
{
public string Name { get; set; }
public string Rank { get; set; }
public decimal Price { get; set; }
}
var fruits = new List<Fruit>()
{
new Fruit(){Name = "りんご", Rank = "A" , Price = 1000 },
new Fruit(){Name = "みかん", Rank = "A" , Price = 600 },
new Fruit(){Name = "ぶどう", Rank = "B" , Price = 1200 },
new Fruit(){Name = "りんご", Rank = "B" , Price = 800 },
new Fruit(){Name = "みかん", Rank = "A" , Price = 500 }
};
【VB】
Private Class Fruit
Public Property Name As String
Public Property Rank As String
Public Property Price As Decimal
End Class
Dim fruits = New List(Of Fruit)() From
{
New Fruit() With {.Name = "りんご", .Rank = "A", .Price = 1000},
New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 600},
New Fruit() With {.Name = "ぶどう", .Rank = "B", .Price = 1200},
New Fruit() With {.Name = "りんご", .Rank = "B", .Price = 800},
New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 500}
}
果物リストを名前で昇順に並び替えます。
【C#】
//名称を昇順で並び替え
var ordered = fruits.OrderBy(itm => itm.Name);
//出力
foreach (var itm in ordered)
Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));
//名称=ぶどう, ランク=B, 値段=1,200
//名称=みかん, ランク=A, 値段=600
//名称=みかん, ランク=A, 値段=500
//名称=りんご, ランク=A, 値段=1,000
//名称=りんご, ランク=B, 値段=800
【VB】
'名称を昇順で並び替え
Dim ordered = fruits.OrderBy(Function(itm) itm.Name)
'出力
For Each itm In ordered
Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=ぶどう, ランク=B, 値段=1,200
'名称=みかん, ランク=A, 値段=600
'名称=みかん, ランク=A, 値段=500
'名称=りんご, ランク=A, 値段=1,000
'名称=りんご, ランク=B, 値段=800
果物リストを名前の昇順、値段の昇順に並び替えます。
一つ目のソート条件である名前はOrderByメソッドで指定し、二つ目のソート条件である値段はThenByメソッドで指定します。
【C#】
//名称の昇順、値段の昇順で並び替え
var ordered = fruits.OrderBy(itm => itm.Name).ThenBy(itm => itm.Price);
//出力
foreach (var itm in ordered)
Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));
//名称=ぶどう, ランク=B, 値段=1,200
//名称=みかん, ランク=A, 値段=500
//名称=みかん, ランク=A, 値段=600
//名称=りんご, ランク=B, 値段=800
//名称=りんご, ランク=A, 値段=1,000
【VB】
'名称の昇順、値段の昇順で並び替え
Dim ordered = fruits.OrderBy(Function(itm) itm.Name).ThenBy(Function(itm) itm.Price)
'出力
For Each itm In ordered
Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=ぶどう, ランク=B, 値段=1,200
'名称=みかん, ランク=A, 値段=500
'名称=みかん, ランク=A, 値段=600
'名称=りんご, ランク=B, 値段=800
'名称=りんご, ランク=A, 値段=1,000
今まで使う必要に迫られたことはないのですが…
OrderByメソッドやThenByメソッドの第二引数にICompareを指定することで、独自の並び替え方法でソートすることができます。
例えば「2015/1/1, 2015/11/11, 2015/5/31, 2015/4, 20」といった日付を表す文字列があったとします。
これらを文字列としてソートすると「20, 2015/1/1, 2015/11/11, 2015/4, 2015/5/31」となります。
日付と考えるのであれば「20, 2015/1/1, 2015/4, 2015/5/31, 2015/11/11」と並んで欲しいです。
このようなとき独自のソート方法を定義します。
独自のソート方法を定義するには
IComparerインターフェイスを実装したクラスを作成し、Compareメソッドに比較方法を記述します。
【C#】
private class CompareDateString : System.Collections.Generic.IComparer<string>
{
public int Compare(string x, string y)
{
//xがyより小さいときはマイナスの数、大きいときはプラスの数、同じときは0を返すようにする
string[] aryX = x.Split('/');
string[] aryY = y.Split('/');
string xDateString;
xDateString = aryX[0].PadLeft(4, '0');
xDateString += (aryX.Length > 1 ? aryX[1].PadLeft(2, '0') : "00");
xDateString += (aryX.Length > 2 ? aryX[2].PadLeft(2, '0') : "00");
string yDateString;
yDateString = aryY[0].PadLeft(4, '0');
yDateString += (aryY.Length > 1 ? aryY[1].PadLeft(2, '0') : "00");
yDateString += (aryY.Length > 2 ? aryY[2].PadLeft(2, '0') : "00");
int i = xDateString.CompareTo(yDateString);
return i;
}
}
【VB】
Private Class CompareDateString : Implements System.Collections.Generic.IComparer(Of String)
Public Function Compare(x As String, y As String) As Integer _
Implements System.Collections.Generic.IComparer(Of String).Compare
'xがyより小さいときはマイナスの数、大きいときはプラスの数、同じときは0を返すようにする
Dim aryX As String() = x.Split("/"c)
Dim aryY As String() = y.Split("/"c)
Dim xDateString As String
xDateString = aryX(0).PadLeft(4, "0")
xDateString += If(aryX.Length > 1, aryX(1).PadLeft(2, "0"), "00")
xDateString += If(aryX.Length > 2, aryX(2).PadLeft(2, "0"), "00")
Dim yDateString As String
yDateString = aryY(0).PadLeft(4, "0")
yDateString += If(aryY.Length > 1, aryY(1).PadLeft(2, "0"), "00")
yDateString += If(aryY.Length > 2, aryY(2).PadLeft(2, "0"), "00")
Dim i As Integer = xDateString.CompareTo(yDateString)
Return i
End Function
End Class
OrderyByメソッドの第二引数にICompareを実装したCompareDateStringを指定します。
【C#】
string[] dateStrings = { "2015/1/1", "2015/11/11", "2015/5/31", "2015/4", "20" };
//普通に昇順でソート
var orderedList1 = dateStrings.OrderBy(str => str);
//出力
foreach (var itm in orderedList1)
Console.WriteLine(itm);
//20
//2015/1/1
//2015/11/11
//2015/4
//2015/5/31
//第二引数にICompareを実装したCompareDateStringを指定しソート
var orderedList2 = dateStrings.OrderBy(str => str, new CompareDateString());
//出力
foreach (var itm in orderedList2)
Console.WriteLine(itm);
//20
//2015/1/1
//2015/4
//2015/5/31
//2015/11/11
【VB】
Dim dateStrings As String() = {"2015/1/1", "2015/11/11", "2015/5/31", "2015/4", "20"}
'普通に昇順でソート
Dim orderedList1 = dateStrings.OrderBy(Function(str) str)
For Each itm In orderedList1
Console.WriteLine(itm)
Next
'20
'2015/1/1
'2015/11/11
'2015/4
'2015/5/31
'第二引数にICompareを実装したCompareDateStringを指定しソート
Dim orderedList2 = dateStrings.OrderBy(Function(str) str, New CompareDateString())
For Each itm In orderedList2
Console.WriteLine(itm)
Next
'20
'2015/1/1
'2015/4
'2015/5/31
'2015/11/11
※VBの場合、コンパイルオプションで「Option Infer」をONにし、型推論を有効にしてください。
.Net(VB C#) LINQのメソッド一覧
0 件のコメント:
コメントを投稿