如何合并不同结构的两个容器(向量/列表),但在C ++中有一个通用参数

时间:2015-08-21 08:32:30

标签: c++ merge containers

将C ++与boost / stl结合使用,如何合并两个不同对象的列表,比如A和B?它们有一些共同的和一些不同的字段/属性,并且不共享唯一的id。

class A
{
   int id;
   double smth;
}

class B
{
   int id;
   std::string name;
   Type type;
}

class C
{
   int id;
   std::string name;
   Type type;
   double smth;
}

所以我的想法是std::list<A>std::list<B>我想轻松将它们合并到std::list<C>

4 个答案:

答案 0 :(得分:1)

提供适配器/转换器并使用它。

struct Type{};

struct A
{
    int id;
    double smth;
};

struct B
{
    int id;
    std::string name;
    Type type;
};

struct C
{
    int id;
    std::string name;
    Type type;
    double smth;

    C(const B& b) : id(b.id), name(b.name), type(b.type){}
    C(const A& a) : id(a.id), smth(a.smth) {}
};

int main() {

    std::vector<A> a = {{5, 0.6f}, {3, 0.3f}};
    std::vector<C> c;
    c.insert(c.end(), a.cbegin(), a.cend());
    return 0;
}

答案 1 :(得分:0)

您可以使用简单的仿函数变换:

<强> Live On Coliru

enum Type { T1,T2,T3,TA };

struct A
{
   int id;
   double smth;
};

struct B
{
   int id;
   std::string name;
   Type type;
};

struct C
{
   int id;
   std::string name;
   Type type;
   double smth;
};

struct MakeC {
    C operator()(A const& a) const { return { a.id, "",     TA,     a.smth }; }
    C operator()(B const& b) const { return { b.id, b.name, b.type, 0.0    }; }
};

#include <iterator>
#include <algorithm>

int main() {
    std::vector<A> as(10);
    std::vector<B> bs(10);

    std::vector<C> cs;

    std::transform(as.begin(), as.end(), back_inserter(cs), MakeC());
    std::transform(bs.begin(), bs.end(), back_inserter(cs), MakeC());
}

答案 2 :(得分:0)

似乎你想获得一个JOIN( - 在SQL中调用它)。执行以下操作:

  • 按ID列出两个列表。
  • 循环并合并它们 - 无论您想要INNER,LEFT,RIGHT还是FULL OUTER JOIN,这里的实际过程都有所不同。我想你想要一个INNER JOIN,即:只有当std::list<C>两个都存在时才在id中包含一个变量。

这是一个完成该任务的小代码:

auto compare =  [](auto const& u, auto const& v) { return u.id < v.id;};

std::list<A> a;
a.sort(compare);
std::list<B> b;
b.sort(compare);

std::list<C> c;
auto ita = std::begin(a);
auto itb = std::begin(b);
while(ita != std::end(a) && itb != std::end(b))
{
    if(ita->id == itb->id)
    {
        c.emplace_back(*ita, *itb);
        ++ita;
        ++itb;
    }
    else if(ita->id < itb->id)
    {
        ++ita;
    }
    else
    {
        ++itb;
    }         
}

为了工作,您还需要C中的构造函数,该构造函数合并AB

C(A const& a, B const& b) : /* assign the stuff */ {}

Demo。它编译并且应该可以工作但是未经测试。

答案 3 :(得分:0)

对于任何正在寻找的人,这是我的解决方案:

   std::transform
   (
      A_vect.begin(), A_vect.end(), 
      std::back_inserter(B_vect), 
      [](const A &a) -> B
      {
         B b;
         b.id   = a.id;
         
         return b;
      }
   );

然而,这最终不会产生一个排序的容器。