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

发布于 2024-10-14 03:01:31 字数 427 浏览 1 评论 0原文

这更多的是一个学习问题。有没有办法可以使用 std::for_each 或 std::transform 编写以下 for 循环?如果没有,boost 中有什么可以帮助解决这个问题吗?该循环只是将向量组成的向量展平为一个长向量。

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

This is more of a learning question. Is there a way I can write the following for-loop using std::for_each or std::transform? If not, is there anything in boost that can help on this? The loop simply flattens a vector of vectors into one long vector.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜司空 2024-10-21 03:01:32

如果您的编译器支持 lambda,这相当简单。 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());
});

If your compiler supports lambdas this is fairly simple. The typedefs help with readability.

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());
});
烟柳画桥 2024-10-21 03:01:32

我知道宏不是很好的做法,但您可以用它们做一些聪明的事情:

#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 来完成您想要实现的目标。

I kno macros aren't great practice but you can do some clever things with them:

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

You can also use std::copy and back_inserter to do what you're trying to achieve.

遇见了你 2024-10-21 03:01:31

除非您有支持 lambda 的编译器,否则我不会更改它以使用其中一种算法。正如所写的那样,它完全清楚。即使您的编译器确实支持 lambda,我也可能不会更改此代码。

一种相对简单的选择是编写一个扁平化迭代器。我在另一个问题的答案中写了一个演示。

如果您确实想要一行代码并且可以使用bind(来自Boost的boost::bindstd::tr1:: TR1 中的 bind 和 C++0x 中的 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)
    )
);

是的,这在技术上是一个“代码行”,因为它是一条语句。唯一的我提取的是指向成员函数类型的 typedef,用于消除重载的 beginend 函数,您不一定需要 typedef this; ,但如果我不这样做,代码需要在 Stack Overflow 上水平滚动。)

I wouldn't change this to use one of the algorithms unless you have a compiler that supports lambdas. It's completely clear as written. Even if your compiler did support lambdas, I'd probably not change this code.

One relatively straightforward option would be to write a flattening iterator. I wrote one for demonstration in an answer to another question.

If you really want a one-liner and can use bind (boost::bind from Boost, std::tr1::bind from TR1, and std::bind from C++0x will all work), then here is how that would look. I warn you in advance: it is horrible.

Edit: Technically this is also illegal. The type of a Standard Library member function is unspecified, so you cannot (portably or correctly) take the address of such a member function. If you could correctly take the address of a Standard Library member function, this is what it would look like:

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

(Yes, that is technically one "line of code" as it is a single statement. The only thing I have extracted is a typedef for the pointer-to-member-function type used to disambiguate the overloaded begin and end functions; you don't necessarily have to typedef this, but the code requires horizontal scrolling on Stack Overflow if I don't.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文