知って得するc# linq to objects編
DESCRIPTION
TRANSCRIPT
知って得する C# LINQ to Objects編
株式会社ハ・ン・ド
プログラマ
馬場翔太
http://baba-s.hatenablog.com/
スライド内容
1. LINQ to Objectsとは
2. LINQ to Objectsの使用例
LINQ to Objectsとは
コレクションを扱うための新しい方法
for文やforeach文を使わず下記の様な処理が行えます
• 条件を満たす要素の数を取得
• 条件を満たす要素を抽出
• 条件を満たす最初の要素を取得
• 昇順にソート
• etc.
LINQ to Objectsを使うために必要なこと
using System.Linq;
この一行をソースコードの先頭に追加するだけです
「using System.Linq;」を追加すると…
配列やリストで多くの拡張メソッドが使用可能になります
• Count
• Where
• First
• OrderBy
• etc.
次のスライドから順番に紹介していきます
LINQ to Objectsの使用例
// 兵士の数を取得します
var result = 0;
foreach (var character in characters)
{
if (character.Job == "Soldier")
{
result++;
}
}
条件を満たす要素の数を取得する
従来のコーディング
// 兵士の数を取得します
var result = characters.Count(c => c.Job == "Soldier");
条件を満たす要素の数を取得する
Countメソッドを使用
// 兵士のみ取得します
var result = new List<Character>();
foreach (var character in characters)
{
if (character.Job == "Soldier")
{
result.Add(character);
}
}
条件を満たす要素を抽出する
従来のコーディング
// 兵士のみ取得します
var result = characters.Where(c => c.Job == "Soldier");
条件を満たす要素を抽出する
Whereメソッドを使用
// すべてのキャラクターから名前だけ取得します
var result = new List<string>();
foreach (var character in characters)
{
result.Add(character.Name);
}
要素を射影する
従来のコーディング
// すべてのキャラクターから名前だけ取得します
var result = characters.Select(c => c.Name);
要素を射影する
Selectメソッドを使用
// 全員が兵士かどうかを判断します
var result = true;
foreach (var character in characters)
{
if (character.Job != "Soldier")
{
result = false;
break;
}
}
すべての要素が条件を満たしているか
従来のコーディング
// 全員が兵士かどうかを判断します
var result = characters.All(c => c.Job == "Soldier");
すべての要素が条件を満たしているか
Allメソッドを使用
// 兵士が存在するかどうかを取得します
var result = false;
foreach (var character in characters)
{
if (character.Job == "Soldier")
{
result = true;
break;
}
}
いずれかの要素が条件を満たしているか
従来のコーディング
// 兵士が存在するかどうかを取得します
var result = characters.Any(c => c.Job == "Soldier");
いずれかの要素が条件を満たしているか
Anyメソッドを使用
// 先頭の兵士を取得します
Character result = null;
foreach (var character in characters)
{
if (character.Job == "Soldier")
{
result = character;
break;
}
}
条件を満たす最初の要素を取得する
従来のコーディング
// 先頭の兵士を取得します
var result = characters.First(c => c.Job == "Soldier");
条件を満たす最初の要素を取得する
Firstメソッドを使用
(条件を満たす要素がない場合は例外になります)
// 先頭の兵士を取得します
var result = characters.FirstOrDefault(c => c.Job == "Soldier");
条件を満たす最初の要素を取得する
FirstOrDefaultメソッドを使用
(条件を満たす要素がない場合は既定値を返します)
// 末尾の兵士を取得します
Character result = null;
for (int i = characters.Length - 1; i >= 0; i--)
{
if (characters[i].Job == "Soldier")
{
result = characters[i];
break;
}
}
条件を満たす最後の要素を取得する
従来のコーディング
// 末尾の兵士を取得します
var result = characters.Last(c => c.Job == "Soldier");
条件を満たす最後の要素を取得する
Lastメソッドを使用
(条件を満たす要素がない場合は例外になります)
// 末尾の兵士を取得します
var result = characters.LastOrDefault(c => c.Job == "Soldier");
条件を満たす最後の要素を取得する
LastOrDefaultメソッドを使用
(条件を満たす要素がない場合は既定値を返します)
var result = characters[characters.Length - 1];
最後の要素を取得する
従来のコーディング
Lastメソッドを使用
var result = characters.Last();
// すべてのキャラクターの中で
// 最も大きな力のパラメータを取得します
var result = 0;
foreach (var character in characters)
{
if (result < character.Power)
{
result = character.Power;
}
}
最大値を取得する
従来のコーディング
// すべてのキャラクターの中で
// 最も大きな力のパラメータを取得します
var result = characters.Max(c => c.Power);
最大値を取得する
Maxメソッドを使用
// すべてのキャラクターの中で
// 最も小さな力のパラメータを取得します
var result = int.MaxValue;
foreach (var character in characters)
{
if (character.Power < result)
{
result = character.Power;
}
}
最小値を取得する
従来のコーディング
// すべてのキャラクターの中で
// 最も小さな力のパラメータを取得します
var result = characters.Min(c => c.Power);
最小値を取得する
Minメソッドを使用
// 最も大きな力を持つキャラクターを取得します
int max = characters.Max(c => c.Power);
var result = characters.First(c => c.Power == max);
最大値を持つ要素を取得する
MaxメソッドとFirstメソッドを使用
// 最も大きな力を持つキャラクターをすべて取得します
int max = characters.Max(c => c.Power);
var result = characters.Where(c => c.Power == max);
最大値を持つ要素をすべて取得する
MaxメソッドとWhereメソッドを使用
// アイテムの購入金額を取得します
var result = 0;
foreach (var item in items)
{
result += item.Price;
}
合計値を取得する
従来のコーディング
// アイテムの購入金額を取得します
var result = items.Sum(c => c.Price);
合計値を取得する
Sumメソッドを使用
// アイテムの平均金額を取得します
var result = 0;
foreach (var item in items)
{
result += item.Price;
}
result /= items.Count;
平均値を取得する
従来のコーディング
// アイテムの平均金額を取得します
var result = items.Average(c => c.Price);
平均値を取得する
Averageメソッドを使用
// 錬金術士のみ錬金術を使います
foreach (var character in characters)
{
var result = character as Alchemist;
if (result != null)
{
result.Alchemy();
}
}
指定された型に一致する要素を抽出する
従来のコーディング
// 錬金術士のみ錬金術を使います
foreach (var result in characters.OfType<Alchemist>())
{
result.Alchemy();
}
指定された型に一致する要素を抽出する
OfTypeメソッドを使用
// すべてのフラグをONで初期化します
bool[] flags = new bool[100];
for (int i = 0; i < flags.Length; i++)
{
flags[i] = true;
}
配列を規定値で初期化する
従来のコーディング
// すべてのフラグをONで初期化します
bool[] flags = Enumerable.Repeat(true, 100).ToArray();
配列を規定値で初期化する
Repeatメソッドを使用
//最新の10件のプレゼントの一覧を取得します
var result = new List<Present>();
for (int i = 0; i < 10; i++)
{
result.Add(presents[i]);
}
指定された数の要素を取得する
従来のコーディング
//最新の10件のプレゼントの一覧を取得します
var result = presents.Take(10);
指定された数の要素を取得する
Takeメソッドを使用
// 11件目以降のプレゼントの一覧を取得します
var result = new List<Present>();
for (int i = 10; i < presents.Length; i++)
{
result.Add(presents[i]);
}
指定された数の要素を読み飛ばす
従来のコーディング
// 11件目以降のプレゼントの一覧を取得します
var result = presents.Skip(10);
指定された数の要素を読み飛ばす
Skipメソッドを使用
// 指定されたページに表示する
// プレゼントの一覧を取得します
var result = presents.Skip(page * 10).Take(10);
ページャーの機能を実装する
SkipメソッドとTakeメソッドを使用
// 価格が安い順にアイテムを取得します
var result = items.OrderBy(c => c.Price);
昇順にソートする
OrderByメソッドを使用
// 価格が安い順にアイテムを取得します
var result = items.OrderByDescending(c => c.Price);
降順にソートする
OrderByDescendingメソッドを使用
// アイテムの順番を逆転させます
var result = items.Reverse();
逆順にする
Reverseメソッドを使用
// 名前の重複を取り除きます
var result = names.Distinct();
重複を取り除く
Distinctメソッドを使用
まとめ
LINQ to Objectsを使用すると…
ソースコードを簡潔に記述できます
• for文が減る
• foreach文が減る
• if文が減る
• 変数が減る
ありがとうございました