2011-01-21 23 views
2

これは学習問題の多くです。 std :: for_eachまたはstd :: transformを使って次のfor-loopを書く方法はありますか?そうでない場合は、これを助けることができる何かが増強されていますか?このループは、ベクトルのベクトルを1つの長いベクトルに単純に平坦化します。std :: for_eachまたはstd :: transformを使ってfor-loopを書く方法は?

vector<vector<int> > int_vectors; 

// ... fill int_vectors 

vector<int> ints; 

for (vector<vector<int> >::const_iterator iter = int_vectors.begin(); iter != int_vectors.end(); ++iter) { 
    ints.insert(ints.end(), iter->begin(), iter->end()); 
} 
+0

私はSTLアルゴリズムとブーストについてもっと学びたいと思っています! –

答えて

4

ラムダをサポートするコンパイラがない限り、これをアルゴリズムの1つを使用するように変更しません。それは書かれているように完全に明確です。あなたのコンパイラがlambdaをサポートしていたとしても、おそらくこのコードを変更しないでしょう。

比較的単純な選択肢の1つは、平坦化イテレータを書くことです。私はan answer to another questionにデモンストレーション用のものを書いた。

あなた本当にはワンライナーをしたいとbind使用することができた場合は(C++ 0xのからブーストからboost::bind、TR1からstd::tr1::bind、そしてstd::bindをするすべての仕事)、そしてここにそれがどのように見えるかです。私は事前に警告します:それは恐ろしいです。

編集:これは技術的にも違法です。標準ライブラリメンバ関数の型は指定されていないので、そのようなメンバ関数のアドレスを(移植可能にまたは正しく)取り込むことはできません。あなたは正しく標準ライブラリのメンバ関数のアドレスを取ることができれば、これは、それは次のようになります。それは、単一のステートメントであるよう

typedef std::vector<int>::iterator (std::vector<int>::*IteratorGetter)(); 

std::for_each(int_vectors.begin(), int_vectors.end(), 
    std::bind(
     std::bind(
      &std::vector<int>::insert<std::vector<int>::iterator>, 
      &ints, 
      std::bind((IteratorGetter)&std::vector<int>::end, &ints), 
      _1, 
      _2 
     ), 
     std::bind((IteratorGetter)&std::vector<int>::begin, _1), 
     std::bind((IteratorGetter)&std::vector<int>::end, _1) 
    ) 
); 

(はい、それは技術的に一つの「コード行」です。私が抽出した唯一のものは、オーバーロードされたbeginend関数を明確にするために使用されるポインタへのメンバ関数型のtypedefであり、必ずしもtypedefする必要はありませんが、コードはスタックオーバーフローで水平スクロールが必要です)

+0

Jamesさん、あなたのフラット化イテレータソリューションを見ましたが、より簡単な1行コードを探していました。上記のコードが気に入らないというわけではありません。私は学びたいだけです! lambdasのコンパイラサポートについて述べました。それはコンパイラによってサポートされる必要がありますか、または::ラムダ作業を高めることができますか? –

+0

@Haitham:純粋なワンライナーの外観を掲載しました。言うまでもありませんが、それはかわいいものではありません。私はBoost.Lambdaを使った解決策がどのようなものか分かりません。私はそれを使用したことはありません。 –

+1

C++は、3行for-loopsの13行の "1行のコード"置換でユーザー自身を苦しめる唯一の著名な言語ですか? @ハサム:for_each、変形、または他のほとんどのものを使ったシナリオは、それらをまだ知らない人によって恣意的に発明されたときに、役に立たない可能性は非常に低いです。代わりに、書籍、記事などにどのように使用されているかなど、他の人がどのように使用しているかを調べ、いつでも[意図的に](http://norvig.com/21-days.html)評価してください。 –

2

コンパイラがラムダをサポートしている場合、これはかなり簡単です。 typedefは可読性に役立ちます。

typedef std::vector<int> VI; 
typedef std::vector<VI> VVI; 

VVI int_vectors; 
VI ints; 

std::for_each(int_vectors.begin(), int_vectors.end(), [&](VI &vec) { 
    ints.insert(ints.end(), vec.begin(), vec.end()); 
}); 
+0

+1:かわいいコード^ _ ^! – Chan

+0

残念ながら、私のコンパイラはlambdasをサポートしていません。それはgcc 3.4.6 ...かなり古いです!しかし、ニースコード! –

0

私はマクロは偉大な練習ではなく、あなたも一緒にいくつかの巧妙なことを行うことができます自演:

#include <algorithm> 
#include <vector> 
#include <iostream> 
#include <iterator> 

using namespace std; 
#define all(v) (v).begin(), (v).end() 
#define foreach(it, v) for(auto it = (v).begin(); it != (v).end(); ++it) 

void main() { 
    vector<int> vi; 
    vector<vector<int>> vvi; 

    foreach(it, vvi) { 
     copy(all(*it), back_inserter(vi)); 
    } 
} 

また、あなたはしようとしている何をするのstd ::コピーとback_inserterを使用することができます達成する。

関連する問題