2015年12月 3日 (木)LINQ話
本日のブログ当番新人プログラマーM.Iです。
働いて半年がたち、慌ただしさにも慣れてきた気がしましたが、年末になると忙しいものは忙しいですね。
学生の頃はよくC#を触っていました。
手軽にツールが作れるのも魅力でしたし、周りの人もC#ができる人が多かったですね。
そのころからコードを短く美しく書けないか色々勉強していました。
その中で出会った文法がLINQです。
ということで今日はLINQの紹介です。
SQLのデータ問い合わせのようにアクセスできないか、という考えで作られたものらしいです。
そういうわけで関数名などはSQLに似ています。
// 1~10の配列のようなものを作る var oneToTen = Enumerable.Range( 1 , 10 ); // 1~10がiに入り、偶数だけにフィルタし、 var oddString = oneToTen.Where( i => i % 2 == 0 ) // それらがelemに入ってくるのでそれぞれを文字列に変換して詰め直す .Select( elem=>elem.ToString() ); |
Selectが情報を加工し、Whereが情報をフィルタするイメージですね。
厳密には配列ではないのですが、今回の記事ではそこに主眼を置くわけではないので配列のようなものと表記しています。
この表記にはいくつかの利点があります。
・アルゴリズムの趣旨がわかりやすくなる
ループならどんなこともできてしまうので、別途関数に分けたりコメントを書かないと趣旨がぼやけます。
これなら用語さえ覚えておけばどんな目的の操作か類推できます。
・変更しやすい
「.」でつなげるとさらに条件を絞り込むといった操作が直観的にできますし、操作の影響も把握しやすくなります。
さてそういったことがC++ではできないかどうか?
cpplinqというライブラリもあるそうです。
ただ私は使った事がないので説明を割愛します。
標準ライブラリの機能では、「.」でつないで絞り込んだり、はできないようです。
Selectにあたるstd::transform
Whereにあたるstd::remove_ifがあります。
remove_ifだけだとイテレータの最後に移動させる動作しかしないので、erase-removeイディオムというのを使い、要素を削除するそうです。
// vectorを作る std::vector< int > oneToTen = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; // 予約する std::vector< std::string > oddString(5); // 偶数を削除する oneToTen.erase( std::remove_if( oneToTen.begin() , oneToTen.end() , [](int elem){ return elem % 2 != 0; } ) , oneToTen.end() ); // 文字列に変換する std::transform( oneToTen.begin() , oneToTen.end() , oddString.begin() , [](int i){ return std::to_string(i); } ); |
一応上のとほぼ同じ動作です。
Whereだと条件に合ったものを残す、remove_ifが条件に合ったものを消すという違いがありますね。
C++11が使えない環境ならラムダ式が使えないので、関数オブジェクトを別途定義する必要があります。
なので条件や変換方法を記述するのが少し長くなりますね。
こういう風に別の言語からも短く美しく書くという知見が得られることもあります。
プログラマーたるもの、いつも新しい技術に触れていたいですね。
| 固定リンク | コメント (0) | トラックバック (0)
「プログラマー」カテゴリの記事
- 技術交流の業(2019.03.07)
- 福袋争奪戦デビュー(2019.01.31)
- 温泉旅行(2019.01.24)
- ゲーセンの近況(2018.11.29)
- 健康的にプログラミングを続けるためのちょっとした習慣(2018.10.18)
この記事へのコメントは終了しました。
コメント