【问题标题】:Extracting a class member from a vector of class instances (as a new vector)从类实例向量中提取类成员(作为新向量)
【发布时间】:2013-06-17 10:06:08
【问题描述】:

我有一个类/结构如下:

struct MyStruct {
  std::string member_one;
  std::string member_two;
};

我创建了一个MyStructstd::vector<MyStruct> 的向量,其长度为N,其成员设置为自定义值:

std::vector<MyStruct> my_struct_vect(10);
// initialize class instances

现在我想将第一个成员 memberOne 提取到一个新向量中。我可以这样做:

std::vector<std::string> member_one_vect(my_struct_vect.size());
for (size_t i = 0; i < my_struct_vect.size(); ++i) {
  member_one_vect[i] = my_struct_vect[i].member_one;
}

我的问题是,是否有一种更快/更优雅/更简洁的方式来执行此操作,而不必每次都编写自定义循环?例如,在 Python 中,我可以通过推导很容易地做到这一点。我并不期待 C++ 中会有类似的东西,但我想知道是否有某种方法可以简化这一点。

更新

感谢在使用 std::transformboost::adaptors::transformed 时的热烈反响。这些非常有用,但为了紧凑,值得注意的是它们依赖于 C++11 中引入的 lambda 函数(可以不使用它们,但这需要定义一个单独的辅助函数)。

那么对于奖励积分,有什么方法可以在 C++03 中以紧凑的方式做到这一点?

【问题讨论】:

标签: c++ stl initialization


【解决方案1】:

你可以使用std::transform:

#include <algorithm> // Necessary for std::transform()

// ...

std::vector<std::string> member_one_vect(my_struct_vect.size());

std::transform(
    my_struct_vect.begin(), my_struct_vect.end(), member_one_vect.begin(),
    [] (MyStruct const& ms)
{
    return ms.member_one;
});

下面是完整代码的样子:

#include <vector>
#include <string>
#include <algorithm>

struct MyStruct {
  std::string member_one;
  std::string member_two;
};

int main()
{
    std::vector<MyStruct> my_struct_vect(10);

    // Initialize my_struct_vect...

    std::vector<std::string> member_one_vect(my_struct_vect.size());

    std::transform(
        my_struct_vect.begin(), my_struct_vect.end(), member_one_vect.begin(),
        [] (MyStruct const& ms)
    {
        return ms.member_one;
    });

    // Do something with member_one_vect...
}

这是live example

【讨论】:

  • 太棒了!感谢您非常详细的回复。我意识到你的答案比 ForEveR 的来得稍微快一些 - 将把这个问题留待一段时间看看还有什么问题,然后接受投票最多的答案。
【解决方案2】:

你可以使用算法。

std::vector<std::string> member_one_vect(my_struct_vect.size());
std::transform(my_struct_vect.begin(), my_struct_vect.end(),
member_one_vect.begin(),
[](const MyStruct& m) { return m.member_one; });

另外,您可以使用boost::adaptors::transformed

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>

std::vector<std::string> member_one_vect(my_struct_vect.size());
std::function<std::string(const MyStruct&)> transform =
[] (const MyStruct& m) { return m.member_one; };
boost::copy(my_struct_vect | boost::adaptors::transformed(transform),
member_one_vect.begin());

【讨论】:

  • 非常有用!我知道必须有一些更好的(STL)方法来做到这一点。我将把这个问题搁置一段时间,看看是否有其他替代答案出现,但最终可能会接受这个答案:)
猜你喜欢
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多