如何合并两个不同结构的容器(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;
}
您可以将转换与简单的函子一起使用:
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
中的构造函数,它合并了 A
和 B
:
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;
}
);
然而,这最终并没有产生排序的容器。
将 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;
}
您可以将转换与简单的函子一起使用:
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
中的构造函数,它合并了 A
和 B
:
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;
}
);
然而,这最终并没有产生排序的容器。