2015-10-22 2 views
5

のベクトルを埋めるためにアルゴリズムを使用するにはどのようにしていベクトル

typedef std::vector<int> IVec; 
typedef std::vector<IVec> IMat; 

と私は少ないコードで次の操作を実行する方法、すなわち、STDのアルゴリズムを使用してIMatを埋めることができますどのように知っていただきたいと思います(すべてのIVecは同じサイズです)?

void fill(IMat& mat){ 
    for (int i=0;i<mat.size();i++){ 
     for (int j=0;j<mat[i].size();j++){ 
      mat[i][j] = i*j; 
     } 
    } 
} 

PS:既に定数を使って行列を埋める方法は私には役に立ちます。そして、好ましくは、プリC++ 11アルゴリズムを使用します。

+2

シースの値はインデックスに依存します...ただループに留まります。 – deviantfan

+1

空のベクトルを初期化する必要がありますか、すでに空でないベクトルの値を入力する必要がありますか?また、インデックスベースの値( 'i * j')、または任意の値(たとえば' 0')で行うこともできますか? – SingerOfTheFall

+0

@SingerOfTheFallあなたの最初の質問を理解しているかどうかわかりません、私の 'IMat'は既に初期化されています、つまり空ではありません。はい、値はインデックスに依存する必要があります。しかし、それはすでに定数でそれを埋めるために役立つだろう。 – user463035818

答えて

3

これはループのダブルよりも優れている場合、私は知らないが、次のようにC++ 11でSTLを使用して、それを行うことが1つの可能な方法は2 for_eachを使用することになります。

int i(0); 
std::for_each(mat.begin(), mat.end(), 
[&i](IVec &ivec){int j(0); std::for_each(ivec.begin(), ivec.end(), 
          [&i,&j](auto &k){k = i*j++;}); ++i;}); 

LIVE DEMO

+2

私は生成の順序が保証されていないことをかなり確信しています=>実装によっては、間違った値を埋めています。 – deviantfan

+0

@deviantfanは、それを知らなかった、驚きの驚き。 – 101010

+1

@deviantfanそれをサポートする証拠はありますか? http://en.cppreference.com/w/cpp/algorithm/generate#Possible_implementationは次のように実装しています:while(first!= last)* first ++ = g(); '。私は*すべての反復子アルゴリズムが連続していると信じていました。たとえば、ラムダが問題ではない場合は、多くの問題があります。 –

5

あなたが既に実装したソリューションが最適です。アルゴリズムを計算するために、両方のオフセットと入力としてi/jを使用することを利用します。

標準的なアルゴリズムでは、要素カウンタのカウンタを保持するイテレータを使用する必要があります。このデータミラーリングは、問題の確実な兆候です。しかし、それはあなたがなりたい空想なる場合でも、1行に、行うことができます。

for_each(mat.begin(), mat.end(), [&](auto& i) { static auto row = 0; auto column = 0; generate(i.begin(), i.end(), [&]() { return row * column++; }); ++row; }); 

しかし、それは行うことができるだけの原因に述べたようにそれが行われるべきであることを意味するものではありません。これにアプローチする最善の方法はfor -loopです。

for(auto i = 0U;i < mat.size();i++) for(auto j = 0U;j < mat[i].size();j++) mat[i][j] = i*j; 

がちなみに私の標準アルゴリズムは、Clang 3.7.0gcc 5.1を正常に動作、およびVisual Studio 2015しかしpreviously I used transform rather than generate上:それはあなたのものだ場合でも、1行にそれを行うことは可能です。そして、λスコープのstatic変数のキャプチャを持つimplementation bugs in gcc 5.1 and Visual Studio 2015があるようです。

+0

もしそれが合っていれば、物を1行に置くのは大変 "私のもの"ですが、決断しなければならない場合、for-loopの本体の周りの '{}'を省略することは禁じられます;) – user463035818

+0

@ tobi303改行はフリーです私はそれらを私の個人的なコードで自由に使用します。 (中括弧に沿って)私はそれがより読みやすくすると思います。しかし、終わりには、この場合の最も重要な決定は、それを1行で行うかどうかではなく、forループで行うことであると私は考えています。 –

+2

+1この声明だけのために: "しかし、述べたように、それを行うことができたということは、 –

3

私はジョナサンの優れた答えについてさらにコメントしたいと思っていました。

今のところC++ 11の構文を無視して、いくつかのサポートクラスを書いていると想像してください(今はどうでもいい)。

我々はおそらく、このようなコードを思い付くことができます:

auto main() -> int 
{ 
    // define a matrix (vector of vectors) 
    IMat mat; 

    // resize it through some previously defined function 
    resize(mat, 10, 10); 

    // get an object that is a pseudo-container representing its extent 
    auto extent = extent_of(mat); 

    // generate values in the pseudo-container which forwards to the matrix 
    std::generate(extent.begin(), 
        extent.end(), 
        [](auto pxy) { pxy.set_value(pxy.x * pxy.y); }); 

    // or even 

    for (auto pxy : extent_of(mat)) { 
     pxy.set_value(product(pxy.coordinates())); 
    } 

    return 0; 
} 

100以降のサポートコードの行数(反復可能なコンテナとそのプロキシは些細ではありません)、これはコンパイルして動作します。

賢い、それは間違いなく、いくつかの問題があることになるよう:

  • はコードの100個の余分な行の小さな問題があります。
  • このコードは実際にはより表現力があり、よりも小さいと思われます。すなわち、あなたのコードが何をしているのかがすぐに分かります。私の場合は、いくつかの前提を設けたり、100行余分なコードについて推論しなければなりません。
  • 私のコードは、あなた

時々小さいがよりあるより多くよりメンテナンス(およびドキュメント)が必要です。