【问题标题】:Building a vector from components contained in another vector type从另一个向量类型中包含的组件构建向量
【发布时间】:2009-08-03 13:15:09
【问题描述】:

我的代码如下所示:

struct First
{
    int f1;
    int f2;
};

struct Second
{
    First s1;
    int s2;
};

std::vector < Second > secondVec;

Second sec;
sec.s1 = First(); 

secondVec.push_back(sec);
secondVec.push_back(sec);

std::vector < First > firstVec;
firstVec.reserve(secondVec.size());

for (std::vector < Second >::iterator secIter = secondVec.begin(); 
         secIter != = secondVec.end();
         ++secIter)
{
    firstVec.push_back(secIter->s1);
}

我想用一个简单的 stl 函数替换这个丑陋的 for 循环,该函数也许可以执行等效的过程。我在想也许std::transform 可以在这里帮助我,但我不确定如何写。

如果 boost 在这里有什么可以提供的,我也很感兴趣。

【问题讨论】:

    标签: c++ algorithm stl boost


    【解决方案1】:

    如果你有 TR1 或 Boost 可用,你可以试试这个:

    std::transform(secondVec.begin(),
                   secondVec.end(),
                   std::back_inserter(firstVec),
                   std::tr1::bind(&Second::s1, _1));
    

    【讨论】:

      【解决方案2】:

      定义将第二个转换为第一个的函子:

      struct StoF { First operator()( const Second& s ) const { return s.s1; } };
      

      然后按如下方式使用:

      transform( secondVec.begin(), secondVec.end(), back_inserter(firstVec), StoF() );
      

      如果您的源向量包含大量元素,您应该考虑调整目标向量的大小以使其更快地工作,如@Goz 回答:

      firstVec.resize( secondVec.size() );
      transform( secondVec.begin(), secondVec.end(), firstVec.begin(), StoF() );
      

      【讨论】:

        【解决方案3】:

        这不是特别难……我试过了,没问题。

        struct First
        {
            int f1;
            int f2;
        };
        
        struct Second
        {
            First s1;
            int s2;
        };
        
        First Replace( Second& sec )
        {
            return sec.s1;
        }
        

        然后用下面的代码复制一下

        std::vector < Second > secondVec;
        
        Second sec;
        sec.s1.f1 = 0; 
        sec.s1.f2 = 1; 
        secondVec.push_back(sec);
        
        sec.s1.f1 = 2; 
        sec.s1.f2 = 3; 
        secondVec.push_back(sec);
        
        std::vector < First > firstVec;
        firstVec.resize( secondVec.size() );
        std::transform( secondVec.begin(), secondVec.end(), firstVec.begin(), Replace );
        

        【讨论】:

        • 为什么不在Replace函数中返回sec.s1
        • 你可以这样做,是的。我看到其他人的回应并认为“这是一个好点”。现在将编辑我的帖子。
        • 虽然出于某种原因,我更喜欢使用 back_inserter(在之前保留时),但您的处理方法即使不是更有效也一样好。
        • 这是一个敲出一小段代码来解决问题的人之一:)
        【解决方案4】:

        你的直觉是对的。虽然由于您使用的是空向量,但您应该为输出迭代器使用 后插入器

        它应该看起来像这样的东西:

        std::transform(secondVec.being(), secondVec.end(), back_inserter(firstVec), yourFunctor)
        

        而 yourFunctor 看起来像这样:

        void youFunctor(First param)
        {
          return param.s1;
        }
        

        编辑:Boost 可以帮助您使用 lambda 函数,因此您不必为此任务创建单独的函子。您还应该注意,lambda 函数函数是 TR1 的一部分,将集成到 C++ 标准库中。

        编辑:这是 Meredith 与 mem_fun(或成员函数适配器)谈论的内容。

         struct Second
        {
            First s1;
            int s2;
            First getS1() const {return s1;};
        };
        

        然后转换将如下所示:

        std::transform(secondVec.being(), 
                       secondVec.end(), 
                       std::back_inserter(firstVec), 
                       std::mem_fun(&Second::getS1))
        

        【讨论】:

        • 您也可以将s1 的getter 添加到Second 类中,然后使用std::mem_fun 将getter 调整为仿函数,而不必编写显式仿函数。我更喜欢这个,因为它让我的代码更有条理,但有些人似乎害怕&lt;functional&gt;
        • Meredith,如果你有时间,我会非常感谢一个示例代码来说明这种方法 - 我很感兴趣!
        • 如果您使用类,这种方法会更好,因为它可以让您封装数据。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-27
        • 1970-01-01
        • 2020-06-04
        • 1970-01-01
        • 1970-01-01
        • 2014-01-22
        • 2016-08-18
        相关资源
        最近更新 更多