如何合并两个不同结构的容器(vectors/lists),但在 C++ 中有一个公共参数

How to merge two containers (vectors/lists) of different structs, but with one common parameter in C++

将 C++ 与 boost/stl 结合使用,如何合并两个不同对象的列表,例如 A 和 B?他们有一些共同点和一些不同点 fields/properties 并且不共享唯一 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>

提供 adaptor/converter 并使用它。

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

您可以将转换与简单的函子一起使用:

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

您似乎想要获得一个 JOIN(--如 SQL 中所称)。执行以下操作:

  • 按 id 对两个列表进行排序。
  • 遍历两者并合并它们——这里的实际过程是不同的,无论您想要内部、左侧、右侧还是完全外部连接。我想您想要一个 INNER JOIN,即:仅当两个 id 都存在时才在 std::list<C> 中包含一个变量。

这里有一段小代码可以实现:

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。它可以编译并且应该可以工作,但未经测试。

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

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

然而,这最终并没有产生排序的容器。