pstade::oven::cycled をしたときに連続して展開して欲しい。
[お題]
pstade::oven::cycled した時に、連続して展開して欲しい。
言葉にするとややこしいんですが、こんな感じです。
{0, 1, 2}|pstade::oven::cycled(4); // {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2} // // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // // こんな感じで展開して欲しい // {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2}
#include <iostream> #include <pstade/oven/cycled.hpp> #include <pstade/oven/transformed.hpp> #include <pstade/oven/matrix.hpp> #include <pstade/oven/concatenated.hpp> #include <pstade/oven/io.hpp> #include <pstade/oven/distance.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> int main(){ namespace oven = pstade::oven; namespace lambda = boost::lambda; int array[] = {0, 1, 2}; std::cout << (array|oven::cycled(4)) << std::endl; std::cout << (array |oven::rows(array|oven::distance, 1) |oven::transformed(lambda::bind(oven::make_cycled, lambda::_1, 4)) |oven::concatenated) << std::endl; return 0; }
[出力]
{0,1,2,0,1,2,0,1,2,0,1,2} {0,0,0,0,1,1,1,1,2,2,2,2}
さて、順を追って説明すると、まず最初に pstade::oven::rows を使用して2次元配列に展開しなおします。
第一引数に range の長さを指定。
{0, 1, 2}|rows(3, 1); // { {0}, {1}, {2} }
次に pstade::oven::transformed を使用して、それぞれの要素に対して pstade::oven::cycled を適用しています。
ここで、boost::lambda を使って、ごにょごにょしていますが、
lambda::_1|cycled(4)
の様な処理をしていると思ってください。
{ {0}, {1}, {2} }|transformed(lambda::bind(make_cycled, lambda::_1, 4)) // { {0, 0, 0, 0}, {1, 1, 1, 1}, {2, 2, 2, 2} }
このままでは2次元配列になっているので、最後に pstade::oven::concatenated を使用して、1次元配列に戻します。
{ {0, 0, 0, 0}, {1, 1, 1, 1}, {2, 2, 2, 2} }|concatenated; // { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 }
これで完成!
ソースだけ見るとごにょごにょしていますが、実際はそんなに難しいことをしていません。
ようは組み合わせですねー。
range 面白いです。
pstade の中に似たようなアダプタがあるかは知らない。
[pstade]
ver 1.04.3