C++でLINQライクな処理(LINQ for C++による方法)
LINQ for C++
LINQは.NET Framework3.5から組み込まれた機能で,C#等の言語でSQLのデータベース操作のようなことを可能とする.「C# is LINQ」と言う方までいほどに便利な機能.
しかし,C++/CLIはLINQに対応する予定はないとのこと.そこで,LINQに似た機能をC++に提供してくれるのがLINQ for C++である.というわけでLINQ for C++を使ってみる.
導入
LINQ for C++はヘッダファイルひとつで実装されているので,以下のページからダウンロードしてきてインクルードするだけで使用できる.NuGetからのインストールも取得可能である.
使用例1
以下に使用例を示す.LINQ for C++を使って,テストの成績のうち国語と英語がともに50点以上の人のリストを取得している.
普通の配列に対して使うことが出来る.コード補完も微妙だし,型明記しなくちゃいけないし,メソッド形式ないしでC#のLINQほど軽快には書けないものの,便利ではある.
#include <cpplinq.hpp> void main() { using namespace cpplinq; struct Seiseki { char Name[256]; int Kokugo; int Sansuu; int Eigo; int Rika; int Shakai; }; Seiseki seisekiList[] = { {"Yamada",98,78,61,83,70}, {"Tanaka",20,33,16,39,48}, {"Yoshida",72,65,92,13,26}, {"Suzuki",49,82,55,11,96}, {"Sasaki",83,47,61,23,60} }; auto result = from_array(seisekiList) >> where([](Seiseki s) {return s.Kokugo > 50 && s.Eigo > 50;}) >> to_vector(); for (int i = 0; i < result.size(); ++ i) printf("%s : 国語%d 英語%d\n", result[i].Name, result[i].Kokugo, result[i].Eigo); }
結果は以下のように表示される.
Yamada : 国語98 英語61 Yoshida : 国語72 英語92 Sasaki : 国語83 英語61
使用例2
無理やりOpenCVで使ってみる.BRISKで特徴点抽出し,オリエンテーションの向きによって表示する際の色を変えている.
#include <opencv2/opencv.hpp> #include <cpplinq.hpp> void main() { using namespace cpplinq; auto image = cv::imread("Penguins.jpg"); auto detector = cv::FeatureDetector::create("BRISK"); std::vector<cv::KeyPoint> keyPoints; detector->detect(image, keyPoints); auto key1 = from(keyPoints) >> where([](cv::KeyPoint k) { return 0 <= k.angle && k.angle < 90;}) >> to_vector(); auto key2 = from(keyPoints) >> where([](cv::KeyPoint k) { return 90 <= k.angle && k.angle < 180;}) >> to_vector(); auto key3 = from(keyPoints) >> where([](cv::KeyPoint k) { return 180 <= k.angle && k.angle < 270;}) >> to_vector(); auto key4 = from(keyPoints) >> where([](cv::KeyPoint k) { return 270 <= k.angle && k.angle < 360;}) >> to_vector(); cv::drawKeypoints(image, key1, image, cv::Scalar(255,0,0), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key2, image, cv::Scalar(0,255,0), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key3, image, cv::Scalar(0,0,255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key4, image, cv::Scalar(255,255,0), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::imshow("Key Point", image); while(cv::waitKey(1) == -1); }