如何使用std :: for_each或std :: transform写这个for循环?

时间:2011-01-21 04:12:23

标签: c++ boost stl foreach transform

这更像是一个学习问题。有没有办法可以使用std :: for_each或std :: transform编写以下for循环?如果没有,那么还有什么可以帮助解决这个问题吗?循环简单地将矢量矢量展平为一个长矢量。

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());
}

3 个答案:

答案 0 :(得分:4)

除非你有一个支持lambda的编译器,否则我不会改变它来使用其中一种算法。它写得非常清楚。即使您的编译器确实支持lambdas,我也可能不会更改此代码。

一个相对简单的选择是编写一个展平迭代器。我在an answer to another question写了一个演示文稿。

如果真的想要一个单行并且可以使用bind(来自Boost的boost::bind,来自TR1的std::tr1::bindstd::bind来自C ++ 0x将全部工作),然后这是看起来如何。我提前警告你:这太可怕了。

编辑:从技术上讲,这也是非法的。标准库成员函数的类型未指定,因此您不能(可移植或正确)获取此类成员函数的地址。如果您可以正确地获取标准库成员函数的地址,那么它就是这样的:

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)
    )
);

(是的,从技术上讲,这是一行“代码”,因为它是一个单一的语句。我唯一提取的是指向成员函数类型的typedef,用于消除重载{{1}的歧义。 }和begin函数;你不一定要输入这个,但如果不这样做,代码需要在Stack Overflow上进行水平滚动。)

答案 1 :(得分:2)

如果你的编译器支持lambdas,这很简单。 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());
});

答案 2 :(得分: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 :: copy和back_inserter来完成您想要实现的目标。