restofwaterimpのぎじゅつMemo

SIerに所属。企画から運用まで幅広くやってます。C#中心に書いてます。

【C#】C#プログラミングのイディオム(6章)配列とList<T>の操作

前回の続き

restofwaterimp.hatenablog.com

配列に対してはLINQを利用することが一番多いと思います。 LINQ以前はfor文やforeachで回しながら、該当の値を探したりしていたのですが、LINQを利用するとすっきり求めることができます。 利用の仕方を知った後に、利用していないソースを見ると「もったいないな〜」と思うようになれると思います。

テーマはこちら

  • 要素の設定
  • コレクションの集計
  • コレクションの判定
  • 単一要素の取得
  • 複数要素の取得
  • その他の操作

要素の設定

連続した文字列を設定する。 LINQならば

//List
Enumerable.Repeat("設定したい値","設定したい数").ToList();
//配列
Enumerable.Repeat("設定したい値","設定したい数").ToArray();

LINQを使わないならば、forとかforeachかな。(でも書籍では非推奨と書いてある) Pythonだと、[num] * count でできるから楽チン

//連続した数値の場合 Enumerable.range(開始の値、作成数).ToArray();  こっちのほうが便利

コレクションの集計

LINQのメソッドで直感的に求めることができる。

//平均
var avarage = numbers.Avarage();
var avarage = books.Avarage(x => x.Price);
//合計
var sum = numbers.Sum();
var sum = books.Sum(x => x.Price);
//最小値
var min = numbers.Min();
var min = numbers.Max();

どれも、LINQのメソッドで指定できる。条件を細かくしたい場合は、whereを利用すれば、条件指定できます。 LINQを利用しない場合、for や foreachで繰り返しながら、if文などのロジックを書きます。

コレクションの判定

該当のデータがあるか、ないかのチェックを行います。 LINQを利用すると便利。 SQLっぽく使えるのがよい。

//条件にあう要素があるか
bool exists = books.Any(x => x.Price < 1000);
//全ての要素が条件に該当するか
bool exists = books.All(x => x.Price < 1000);

単一要素の取得

アプリを作る時によく使うのがこの関連。 比較よりも該当するデータを取得する機能の方がよく使います。

/*Firstも最初の一件を取得だが、見つからないと、InvalidOperationExceptionが発生する。
 値が見つからない場合にDefaultの値を戻すこれらのメソッドを必ず使う*/
//最初の1件だけ
var text = books.FirstOrDefault(x => x.Price == 1000);
//最後の1件だけ
var text = books.LastOrDefault(x => x.Price == 1000);
//最初の位置を求める ⬅︎ これはメソッドの方がいいようです。確かに、LINQで取得は見たことがない。。。
var index = words.FindIndex(x => x < 0);

複数要素の取得

条件で指定するのはwhereメソッドを利用します。 書籍に書いてあるTakeメソッドは使ったことなかった。該当件数のみほしいとかなかったので。 取得した後、for文で回すよりはTakeの方がいいかも

//5より大きいのを最大3つ取得。3つなくても、取得した数だけ戻す。
var result = numbers.where(x => x > 5)
                                   .Take(3);

条件分岐のwhileに相当する TakeWhileやSkipWhileも記載がありますが、あまり使わないなー。

その他の処理

他にも単一化のDistinct()やOrderByなど、SQLぽいメソッドがたくさんあり、使えると便利です。 本書のColumnに記載の「要素の削除」については、そうだよね。と納得する部分でした。

リストや配列の中から、一部のデータを除外する時にforを利用しようとする人を見たことがあります。 forないでインプットにしている要素を削除すると、forの添え字が崩れ、正しくループしなかったり、 InvalidOperationExceptionが発生します。 そのため、forを利用するのではなく、 * 既存の要素をremoveAllで削除 * 取得したい値だけど別の変数に移動する のどちらかを利用して対処するのが良いです。

この章も知っていると便利というものが多かったです。 C#を使うならLINQをしっかり覚えよう!といった感じの章でした。

つづく