2015年06月28日

LINQ to Objectサンプル(15): リストを一定の値で埋める

   このエントリーをはてなブックマークに追加 Clip to Evernote
リストの要素を一定に値(ここでは-1)で埋めるコードを示します。

■ループを使ったコード
var list = new List<int>();
for (int i = 1; i <= 20; i++) {
    list.Add(-1);
}
list.ForEach(Console.WriteLine);


■LINQを使ったコード
var list = Enumerable.Repeat(-1, 20).ToList();
list.ForEach(Console.WriteLine);

Enumerable.Repeatメソッドで、同じ値を繰り返すシーケンスを作り出し、ToLIst()でリストに変換しています。ToArray()を使えば、配列に変換できます。
この例では、ループを使ったコードと等価にするために、あえてToListメソッドを使っていますが、IEnumerableのまま利用できるのであれば、あえて、リストや配列にすること必要はありません。

特定の文字列で埋めたいときにも同じです。
var list = Enumerable.Repeat("(unknown)" , 20).ToList();
list.ForEach(Console.WriteLine);

  

Posted by gushwell at 22:00Comments(0)TrackBack(0)

2015年06月24日

LINQ to Objectサンプル(14): 2つのリストの和集合を求める

   このエントリーをはてなブックマークに追加 Clip to Evernote
2つのリストの要素を重複の無いように併合し、新たなリストを生成する例です。

■ループを使ったコード
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 0, 2, 4, 6, 8 };
List<int> ans = new List<int>(list1);
foreach (var n in list2) {
    if (!ans.Contains(n))
        ans.Add(n);
}
ans.Sort();
ans.ForEach(Console.WriteLine);

この例では、併合後に、昇順にソートしています。
ans には、{0,1,2,3,4,5,6,8 } が格納されます。

■LINQを使ったコード
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 0, 2, 4, 6, 8 };
var ans = list1.Union(list2)
               .OrderBy(n => n)
               .ToList();
ans.ForEach(Console.WriteLine);

Unionメソッドで和集合を取り、OrderByで並び順を変えています。

LINQ にはその他、差集合を得る Except、積集合を得るIntersectメソッドもあります。

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2015年06月21日

LINQ to Objectサンプル(13): 2つのリストが等しいか調べる

   このエントリーをはてなブックマークに追加 Clip to Evernote
2つのシーケンス(リストや配列など)の要素が等しいかを調べるコードです。

■ループを使ったコード
var list1 = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
var list2 = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
bool equal = true;
if (list1.Count != list2.Count) {
    equal = false;
} else {
    for (int i = 0; i < list1.Count; i++) {
        if (list1[i] != list2[i]) {
            equal = false;
            break;
        }
    }
}
Console.WriteLine(equal);


2つの要素数が同じときだけ、ループで各要素を比較しています。

■LINQを使ったコード
var list1 = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
var list2 = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
bool equal = list1.SequenceEqual(list2);
Console.WriteLine(equal);


LINQでは、SequenceEqualsメソッド呼び出すだけです。

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2015年06月17日

LINQ to Objectサンプル(12): ある条件以降の要素を複写する

   このエントリーをはてなブックマークに追加 Clip to Evernote
ここでは、リストを操作しマイナスが見つかったらそれ以降を別のリストに複写する例です。

■ループを使ったコード
var list = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
var ans = new List<int>();
bool find = false;
for (int i = 0; i < list.Count; i++) {
    if (list[i] < 0)
        find = true;
    if (find)
        ans.Add(list[i]);
}
ans.ForEach(Console.WriteLine);

このコードはちょっと無理やり感が否めないですが、まあ他の方法でもにたりよったりでしょう。
FindIndexメソッドを使い、その後複写のコードを書くという方法ありますね。


■LINQを使ったコード
var list = new List<int> { 9, 7, 5, 4, 2, 4, 0, -4, 8, -1, 0, 4 };
var ans = list.SkipWhile(n => n >= 0).ToList();
ans.ForEach(Console.WriteLine);


LINQを使ったコードでは、SkipWhileメソッドを使っています。指定した条件に一致している間は、要素を読み飛ばすメソッドです。
ここでは正の間だけスキップし、それ以降を取り出しています。

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2015年06月14日

LINQ to Objectサンプル(11): 条件に一致する最後のインデックスを求める

   このエントリーをはてなブックマークに追加 Clip to Evernote
要素そのものを取り出すのではなく、何番目の要素かを知りたい場合というのも良くありあす。
ここでは、配列、リストなどから、ある条件に一致する要素のインデックス(最後に見つかったもの)を求めるコードをお見せします。

■ループを使ったコード
var list = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, 8, -1, 0, 4 };
int index = -1;
for (int i = 0; i < list.Count; i++) {
    if (list[i] < 0)
        index = i;
}
Console.WriteLine(index);


■LINQを使ったコード
var list = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, 8, -1, 0, 4 };
int index2 = list.Select((n, ix) => new { n, ix })
                 .Last(o => o.n < 0).ix;
Console.WriteLine(index2);


LINQを使ったコードでは、Selectメソッド(引数を2つ受け取るdelegateを引数に取るメソッド)を使い、要素の値とインデックスを対にした匿名クラスに変換しています。
その後、Lastメソッドで条件指定し、最後のインデックスを返しています。
短いコードなので、匿名クラスのメンバーにはプロパティ名を指定していませんが、 これが気になるって人は、匿名クラスを指定する際に、プロパティ名を指定すればよいでしょう。

例えば、

list.Select((n, ix) => new { Value=n, Index=ix })

といった感じでしょうか?

なお、Lastメソッドを使っているので、条件に一致する要素がなかった場合は、例外が発生します。

  
Posted by gushwell at 14:29Comments(0)TrackBack(0)

2015年06月10日

LINQ to Objectサンプル(10): 項目間を任意の文字列でつなぐ

   このエントリーをはてなブックマークに追加 Clip to Evernote
配列等に格納されている値を文字列に変換し、”-“でつなぐコードです。

下記の例では、

“123-345-567-789″

が表示されます。

■ループを使ったコード
int[] nums = new int[] { 123, 345, 567, 789 };
string s = nums[0].ToString();
for (int i = 1; i < nums.Length; i++)
    s += "-" + nums[i].ToString();
Console.WriteLine(s);


■LINQを使ったコード
int[] nums = new int[] { 123, 345, 567, 789 };
string s = nums.Select(n => n.ToString())
               .Aggregate((t, e) => t + "-" + e);
Console.WriteLine(s);

Aggregateメソッドは、とっつきにくいメソッドですが、いろんな場面で利用できる強力なメソッドです。
Sum, Average, Min, Max などを使ったサンプルも Aggreagetを使って書き換えることができます。 興味のある方はチャレンジしてください。

LINQとは関係ないですが、String.Join使えば、いいんじゃないのという意見も出そうなので、String.Join 使った例も掲載します。

int[] nums = new int[] { 123, 345, 567, 789 };
string s = string.Join("-", nums);
Console.WriteLine(s);

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2015年06月07日

LINQ to Objectサンプル(09): 重複を排除する

   このエントリーをはてなブックマークに追加 Clip to Evernote
数値のリストから重複を排除した新たなリストを作成しています。

■ループを使ったコード
var list = new List<int> { 19, 17, 15, 24, 12, 17, 14, 20, 12, 28, 19, 30, 24 };
var result = new List<int>();
foreach (var n in list) {
    if (!result.Contains(n))
        result.Add(n);
}
result.ForEach(Console.WriteLine);


■LINQを使ったコード
var list = new List<int> { 19, 17, 15, 24, 12, 25, 14, 20, 12, 28, 19, 30, 24 };
var result = list.Distinct();
result.ToList().ForEach(Console.WriteLine);

LINQでは、Distinctメソッドを使うだけです。簡単ですね。

  
Posted by gushwell at 22:00Comments(0)TrackBack(0)

2015年06月03日

LINQ to Objectサンプル(08): 条件を満たす要素をN個取り出す

   このエントリーをはてなブックマークに追加 Clip to Evernote
配列などから、条件を満たす要素を指定した個数だけ取り出す例です。
ここでは、正の数を5個取り出しています。


■ループを使ったコード
var list = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, 8, -1, 0, 4 };
var ans = new List<int>();
int count = 0;
foreach (var n in list) {
    if (n > 0) {
        ans.Add(n);
        count++;
        if (count >= 5)
            break;
    }
}
ans.ForEach(Console.WriteLine);

■LINQを使ったコード
var list = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, 8, -1, 0, 4 };
var ans = list.Where(n => n > 0).Take(5);
ans.ToList().ForEach(Console.WriteLine);

LINQでは、WhereメソッドとTakeメソッドを使います。
Takeメソッドは、指定した個数分の要素がなかったときでもエラーにはならず、最後の要素までを取得します。
LINQのコードがすばらしいのは、型安全性を保ちつつ、型がintに固定されていない点です。longでも、decimalでもそのまま使えます。
上記コードでは、リストのコンストラクタの呼び出しの時だけ、型情報 int が現れるだけです。

  
Posted by gushwell at 23:00Comments(0)TrackBack(0)