让
typedef pair<int, double> Element;
然后我有两个向量:
vector<Element> A, B;
这些向量按Element.first
中的整数排序。我想得到第三个向量C
,它是A
和B
的联合。这听起来像set_union,但在A[i].first == B[j].first
时我需要不同的行为。 set_union
只会选择要包含在C
中的其中一个源元素,但我需要将结果“合并”两个元素。换句话说,就像这样:
C[k].first = A[i].first; // == B[j].first. set_union does this
C[k].second = A[i].second + B[j].second; // set_union does NOT do this.
我很感兴趣,如果可以使用标准库(或类似Boost)。手动执行此操作的代码并不是特别复杂,但我不想重新发明轮子。
我能找到的唯一其他相关操作是merge。它也不会合并元素,并且会涉及另一个组合传递。
答案 0 :(得分:9)
我认为std::merge
与boost::function_output_iterator
的使用非常简洁。
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/function_output_iterator.hpp>
/* Convenience type alias for our element. */
using Elem = std::pair<int, double>;
/* Convenience type alias for the container of our elements. */
using Elems = std::vector<Elem>;
/* Our appender that will be created with boost::function_output_iterator. */
class Appender {
public:
/* Cache the reference to our container. */
Appender(Elems &elems) : elems_(elems) {}
/* Conditionally modify or append elements. */
void operator()(const Elem &elem) const {
if (!elems_.empty() && elems_.back().first == elem.first) {
elems_.back().second += elem.second;
return;
} // if
elems_.push_back(elem);
}
private:
/* Reference to our container. */
Elems &elems_;
}; // Appender
int main() {
// Sample data.
Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
Elems result;
// Merge and use appender to append elements.
std::merge(std::begin(lhs),
std::end(lhs),
std::begin(rhs),
std::end(rhs),
boost::make_function_output_iterator(Appender(result)));
// Print result.
for (const auto &elem : result) {
std::cout << elem.first << ' ' << elem.second << std::endl;
} // for
}
打印:
1 3.6
2 3
3 5.5
4 2.2
5 3.4
请注意。 function_output_iterator建议使用Benjamin Lindley。
答案 1 :(得分:1)
以下是使用独立通用算法merge_elements
的实现:
#include <algorithm>
#include <utility>
template <typename LInput, typename RInput, typename Output>
Output merge_elements(LInput lbegin, LInput lend,
RInput rbegin, RInput rend,
Output out) {
while(true) {
if (lbegin == lend) {
return std::copy(rbegin, rend, out);
}
if (rbegin == rend) {
return std::copy(lbegin, lend, out);
}
if (lbegin->first < rbegin->first) {
*out++ = *lbegin++;
} else if (rbegin->first < lbegin->first) {
*out++ = *rbegin++;
} else {
*out++ = std::make_pair(lbegin->first, lbegin->second + rbegin->second);
++lbegin;
++rbegin;
}
}
}
#include <iostream>
#include <iterator>
#include <vector>
/* Convenience type alias for our element. */
using Elem = std::pair<int, double>;
/* Convenience type alias for the container of our elements. */
using Elems = std::vector<Elem>;
int main() {
// Sample data.
Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
Elems result;
// Merge and use appender to append elements.
merge_elements(std::begin(lhs),
std::end(lhs),
std::begin(rhs),
std::end(rhs),
std::back_inserter(result));
// Print result.
for (const auto &elem : result) {
std::cout << elem.first << ' ' << elem.second << std::endl;
} // for
}
它不需要增强,但与mpark的增强解决方案几乎完全相同。有趣的是,这个算法非常通用,可以与std::map<int,double>
以及std::vector<std::pair<int,double>>
一起保持不变:
#include <iostream>
#include <iterator>
#include <map>
/* Convenience type alias for the container of our elements. */
using Elems = std::map<int, double>;
int main() {
// Sample data.
Elems lhs {{1, 2.3}, {2, 3}, {5, 3.4}};
Elems rhs {{1, 1.3}, {3, 5.5}, {4, 2.2}};
Elems result;
// Merge and use appender to append elements.
merge_elements(std::begin(lhs),
std::end(lhs),
std::begin(rhs),
std::end(rhs),
std::inserter(result, result.begin()));
// Print result.
for (const auto &elem : result) {
std::cout << elem.first << ' ' << elem.second << std::endl;
} // for
}