提问人:acegene 提问时间:6/23/2021 最后编辑:acegene 更新时间:6/23/2021 访问量:236
std::set_union 的替代方法,带有用于合并交集元素的附加谓词参数
Alternative to std::set_union with additional predicate parameter for merging elements from the intersection
问:
给定两个排序的容器和 std::set_union,我们可以提供一个谓词来确定两个元素何时相等。我想提供一个额外的谓词,它将合并相等的元素(容器的交集)并将结果插入到输出容器中。
请注意下面的“预期输出”部分,set_union和unknown_func的向量有何不同。
是否有一种算法可以模拟下面“预期输出”所描述的行为?如果只有更复杂的方法可以产生这种行为,您能建议我从哪里开始这样做吗?最好最终解决方案仅利用 std/stl 库提供的功能。
示例代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
struct CustomStruct{
CustomStruct(const int f1, const int f2) : field_1(f1), field_2(f2) {}
int field_1;
int field_2;
};
void print_vector(const std::string& str, const std::vector<CustomStruct>& vec){
std::cout << str << std::endl;
for (const auto& val: vec){
std::cout<< val.field_1 << ", " << val.field_2 << std::endl;
}
}
int main()
{
std::vector<CustomStruct> vec_a;
std::vector<CustomStruct> vec_b;
std::vector<CustomStruct> vec_set_union;
std::vector<CustomStruct> vec_unknown_func;
for (int i = 0; i < 4; ++i){ vec_a.emplace_back(i, 2); }
for (int i = 2; i < 4; ++i){ vec_b.emplace_back(i, 3); }
print_vector("VEC_A", vec_a);
print_vector("VEC_B", vec_b);
const auto compare = [](const CustomStruct& lhs, const CustomStruct& rhs){
return lhs.field_1 < rhs.field_1;
};
std::set_union(vec_a.begin(), vec_a.end(),
vec_b.begin(), vec_b.end(),
std::back_inserter(vec_set_union),
compare
);
print_vector("VEC_SET_UNION", vec_set_union);
const auto merge_duplicate = [](const CustomStruct& lhs, const CustomStruct& rhs){
return CustomStruct(lhs.field_1, lhs.field_2 + (rhs.field_2*rhs.field_2));
};
// std::unknown_func(vec_a.begin(), vec_a.end(),
// vec_b.begin(), vec_b.end(),
// std::back_inserter(vec_unknown_func),
// compare,
// merge_duplicate
// );
// THE COMMENTED CODE ABOVE WOULD NEED TO ALLOW 'VEC_UNKNOWN_FUNC' to have
// the 'Expected output' supplied as part of this question
print_vector("VEC_UNKNOWN_FUNC", vec_unknown_func);
}
预期输出
VEC_A
0, 2
1, 2
2, 2
3, 2
VEC_B
2, 3
3, 3
VEC_SET_UNION
0, 2
1, 2
2, 2
3, 2
VEC_UNKNOWN_FUNC
0, 2
1, 2
2, 11
3, 11
感谢您抽出宝贵时间,请告诉我是否可以进一步澄清。
答:
1赞
Caleth
6/23/2021
#1
正如@Useless在评论中建议的那样,要在 上做额外的事情,你应该根据该算法写一些东西。<algorithm>
改编自可能的实施:
template<class InputIt1, class InputIt2,
class OutputIt, class Compare,
class BinaryOp>
OutputIt set_union_transform(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp,
BinaryOp binary_op)
{
for (; first1 != last1; ++d_first) {
if (first2 == last2)
return std::copy(first1, last1, d_first);
if (comp(*first2, *first1)) {
*d_first = *first2++;
} else if (comp(*first1, *first2)) {
*d_first = *first1++;
} else {
*d_first = binary_op(*first1++, *first2++);
}
}
return std::copy(first2, last2, d_first);
}
评论
0赞
acegene
6/23/2021
感谢您对如何调整内容以用于自定义用途的帮助:)<algorithm>
1赞
Daniel Dearlove
6/23/2021
#2
只是抨击键盘,但我认为你想要这样的东西:
std::vector<CustomStruct> vec_set_intersection1;
std::vector<CustomStruct> vec_set_intersection2;
// Find the duplicate objects in the first vector
std::set_intersection(vec_a.begin(), vec_a.end(),
vec_b.begin(), vec_b.end(),
std::back_inserter(vec_set_intersection1),
compare);
// Find the duplicate objects in the second vector
std::set_intersection(vec_b.begin(), vec_b.end(),
vec_a.begin(), vec_a.end(),
std::back_inserter(vec_set_intersection2),
compare);
// Apply the transformation
std::transform(vec_set_intersection1.begin(), vec_set_intersection1.end(),
vec_set_intersection2.begin(), vec_set_intersection2.end(),
std::back_inserter(vec_unknown_func),
merge_duplicate);
评论
0赞
acegene
6/23/2021
据我了解,这将正确转换交集,但不包括每个向量独有的元素。但是,有趣的是,这如何颠倒传递给每个set_intersection调用的参数的顺序。这允许从每个向量中提取值,这些值是交集的一部分,以便在转换调用中使用,很酷!
评论
set_union_transform
merge_duplicate
std