Unityに関連する記事です

 前回に引き続き、従来の記法を活用しながら、LINQ の学習を行います。
処理を比較し、置き換えていきながら理解を深めましょう。

 前回はこちらです。

  => 既存の処理をリファクタリングして学ぶ LINQ 活用例

 LINQ には非常に多数のメソッドが用意されています。

 その中から紹介します。



ー作クラスのコレクションから特定の条件を満たす要素を抽出する ーWhere メソッドー


 前回の復習から行います。

 クラスを List で管理している場合のフィルタリングです。

 まずは共通で利用するクラスを作成します。

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}



 従来のコードです。

List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<Person> adults = new List<Person>();

foreach (Person person in people) {
    if (person.Age >= 18) {
        adults.Add(person);
    }
}

 このコードでは、peopleリストから18歳以上のPersonを見つけて、adultsリストに追加しています。



 それではこの処理を LINQ を使い、Where メソッドに置き換えていきます。

List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<Person> adults = people.Where(person => person.Age >= 18).ToList();

 Where()メソッドを使って18歳以上のPersonをフィルタリングし、.ToList()で新しいリストに変換します。


⊆作クラスのコレクションの要素を別の情報に置き換える ーSelect メソッドー


 従来のコードです。


List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<string> names = new List<string>();

foreach (Person person in people) {
    names.Add(person.Name);
}

 ここでは、peopleリストの各Personから名前を取得し、namesリストに追加しています。



 それではこの処理を LINQ を使い、Select メソッドに置き換えていきます。


List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<string> names = people.Select(person => person.Name).ToList();

 Select()メソッドを使ってPersonオブジェクトから名前を抽出し、その結果を新しいリストに変換しています。


コレクション内の要素の合計を計算する ーSum メソッドー


 こちらの従来のコードでは、リストの全ての要素の合計を計算しています。
 
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
int sum = 0;

foreach(int num in numbers){
    sum += num;
}



 それではこの処理を LINQ を使い、Sum メソッドに置き換えていきます。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};
int sum = numbers.Sum();

 Sum()メソッドはリストの全ての要素の合計を返します


<クラス内の指定した要素のみを合計する ーSum メソッドの応用ー>


 Sum メソッドにはオーバーロードがあり、引数にメソッドを取ることができます。
これを使って、特定のプロパティに基づいて合計を求めることができます。

 例えば、Person オブジェクトのリストから全員の年齢の合計を計算する場合、次のようにします。


List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

int totalAge = people.Sum(person => person.Age);

 このコードでは、.Sum()メソッドにperson => person.Ageというメソッドを渡しています。

 これにより、Sumはリスト内の各PersonオブジェクトのAgeプロパティの合計を計算します。


ぅ灰譽ション内を特定の順序に並べ替える ーOrderBy メソッド、OrderByDescending メソッドー


 昇順ソート、降順ソートの機能です。
これらは特定の順序に並べ替えるために使用されます。

 以下に、Personオブジェクトのリストを年齢で昇順および降順に並べ替える例を示します。

 まずは従来の処理で行うケースから提示します。


<昇順ソート>
List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));


<降順ソート>
List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

people.Sort((p1, p2) => p2.Age.CompareTo(p1.Age));

 この例では、Sort メソッドを使用して people リストを直接ソートしています。
このメソッドは、引数に Comparison<T> デリゲートをとります。ここでは、ラムダ式を使用して Person オブジェクトの Age プロパティに基づく比較を定義しています。

 しかし、注意点として、これらの処理は元の people リスト自体を変更します。つまり、元の順序を保持したい場合には、新しいリストを作成してからソートするか、
次に提示する LINQ の OrderBy または OrderByDescending を使用することが適しています。

 これらのLINQメソッドは元のコレクションを変更せず、新しい順序付けられたシーケンスを生成することができますので、元のコレクションは保持されます。



<昇順ソート>

 OrderBy(昇順) メソッドを利用します。

List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<Person> orderedPeople = people.OrderBy(person => person.Age).ToList();



<降順ソート>

 OrderByDescending(降順)を利用します。

List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

List<Person> orderedPeople = people.OrderByDescending(person => person.Age).ToList();

 ここでは、OrderByとOrderByDescendingメソッドにperson => person.Ageというメソッドを渡しています。
これにより、並べ替えは各PersonオブジェクトのAgeプロパティに基づいて行われます。
 

ソ萢の結果を配列や Dictinary に変換する ーToArray メソッド、ToDictinary メソッドー


 ToList メソッドと同様に、ToArrayメソッドを使ってLINQの結果を配列に変換することもできます。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};
int[] results = numbers.Where(num => num > 2).ToArray();

 この例では、Whereメソッドでフィルタリングした結果を List から配列に変換しています。



 また、ToDictionaryメソッドを使って、LINQの結果をDictionaryに変換することもできます。

 例えば、Personクラスのリストを、名前をキーとするDictionaryに変換する例を考えてみましょう:

List<Person> people = new List<Person> {
    new Person { Name = "John", Age = 25 },
    new Person { Name = "Anna", Age = 30 },
    new Person { Name = "Mike", Age = 18 }
};

Dictionary<string, Person> peopleDict = people.ToDictionary(person => person.Name);

 この例では、ToDictionaryメソッドにperson => person.Nameというメソッドを渡しています。
このメソッドは、各Personオブジェクトから名前を取り出し、それを新しいDictionaryのキーとします。Dictionaryの値は、元のPersonオブジェクトになります。


Ε灰譽ションの最初の要素を取り出す ーFirst / FirstOrDefault メソッドー


 これらのメソッドはシーケンスから最初の要素を返します。
 
 FirstOrDefaultの場合、シーケンスが空の場合はデフォルト値を返します。

 最初に従来の処理です。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int firstNumber = numbers[0];

 ただし、リストが空でないことを確認するためのチェックを含めるべきです。



 それではこの処理を LINQ を使い、First / FirstOrDefault メソッドに置き換えていきます。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int firstNumber = numbers.First();

 また、引数にメソッドを取ることで、条件を満たしている最初の要素を取得することが出来ます。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int firstNumber = numbers.FirstOrDefault(x => x >= 2);




 これらは例えばゲームの敵のリストから最初の敵を取得する際に使えます。

List<Enemy> enemies = GetEnemies();
Enemy firstEnemy = enemies.First();

 また、条件付きで最初の要素を取得することもできます。
この場合、List.Find メソッドと同じように、最初に条件に合致した要素を取得します。

Enemy firstStrongEnemy = enemies.FirstOrDefault(enemy => enemy.Strength > 100);

 そのため、覚えておくと便利な機能です。


Д灰譽ションの最後の要素を取り出す ーLast / LastOrDefault メソッドー


 これらのメソッドはシーケンスから最後の要素を返します。
LastOrDefaultの場合、シーケンスが空の場合はデフォルト値を返します。

 それでは従来の処理です。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int lastNumber = numbers[numbers.Count - 1];

 ただし、リストが空でないことを確認するためのチェックを含めるべきです。



 それではこの処理を LINQ を使い、Last / LastOrDefault メソッドに置き換えていきます。


List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int lastNumber = numbers.Last();

 また、引数にメソッドを取ることで、条件を満たしている最後の要素を取得することが出来ます。

List<int> numbers = new List<int> {1, 2, 3, 4, 5};

int lastNumber = numbers.LastOrDefault(x => x <= 2);




 これらは例えばプレイヤーのアクションのリストから最後のアクションを取得する際に使えます。

List<Action> actions = GetPlayerActions();
Action lastAction = actions.Last();

 First と同じように条件付きで最後の要素を取得することもできます。

Action lastJumpAction = actions.LastOrDefault(action => action.Type == ActionType.Jump);



  => 既存の処理をリファクタリングして学ぶ LINQ 活用例

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます