C++ 类似于'std::set_intersection',但生成成对的相等元素
我得到了两个按某些标准排序的容器,例如,按ID号排序的人 我希望通过相同的标准找到两个容器共有的所有元素,并且我希望访问两个被认为相等的元素 我考虑执行合并,然后手动扫描相等的相邻元素。但也许有一个更优雅的算法C++ 类似于'std::set_intersection',但生成成对的相等元素,c++,c++11,C++,C++11,我得到了两个按某些标准排序的容器,例如,按ID号排序的人 我希望通过相同的标准找到两个容器共有的所有元素,并且我希望访问两个被认为相等的元素 我考虑执行合并,然后手动扫描相等的相邻元素。但也许有一个更优雅的算法 struct Employee { int id; int salary; Employee(int id, int salary); }; struct ById { bool operator()(const Employee& left
struct Employee
{
int id;
int salary;
Employee(int id, int salary);
};
struct ById
{
bool operator()(const Employee& left, const Employee& right) {
return left.id < right.id;
}
};
std::vector<Employee> first = { Employee(10, 1000),
Employee(12, 1000),
Employee(31, 10000) }; // Note: sorted by Id
std::vector<Employee> second = { Employee(1, 1500),
Employee(10, 2000),
Employee(31, 12000) }; // Note: sorted by Id
// prints the following:
// [id: 10, salary: 1000], [id: 10, salary: 2000] // id 10 exists in both containers
// [id: 31, salary: 10000], [id: 31, salary: 12000] // id 31 exists in both containers
MySetIntersection( // <--- I WANT TO KNOW HOW TO IMPLEMENT THIS
begin(first), end(first),
begin(second), end(second),
ById(),
[] (const Person& left, const Person& right) {
std::cout << "[" << left << "], [" << right << "]" std::endl;
}
);
到目前为止你试过什么?这似乎是一个相当简单的算法:
template<typename ForwardIterator1, typename ForwardIterator2, typename Func>
void for_each_intersecting(ForwardIterator1 begin1, ForwardIterator1 end1, ForwardIterator2 begin2, ForwardIterator2 end2, Func what) {
while( (begin1 != end1) && (begin2 != end2) ) {
if( *begin1 < *begin2 )
++begin1;
else if( *begin2 < *begin1 )
++begin2;
else
what(*begin1++, *begin2++);
}
}
但请注意,这可能会比原始答案慢,占用更多内存
或者,如果没有lambdas:
#include <iostream>
#include <algorithm>
#include <functional>
struct employee {
int id, salary;
bool operator<(const employee& e) { return id < e.id; }
bool operator==(const employee& e) { return id == e.id; }
};
int main() {
std::vector<employee> v1 { { 1, 1500 }, { 10, 2000 }, { 15, 2500 }, { 16, 1000 } };
std::vector<employee> v2 { { 10, 1500 }, { 13, 2000 }, { 15, 500 }, { 19, 1300 } };
std::vector<employee> v3; v3.reserve(v1.size()+v2.size());
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
for( auto a = v3.begin(), e = v3.end(); (a = std::adjacent_find(a, e)) != e; ++a ) {
std::cout << a->id << ' ' << a->salary << ' ';
++a;
std::cout << a->id << ' ' << a->salary << '\n';
}
}
看起来马萨在我测试的时候打败了我,但无论如何我都会用比较函数来展示它
template<typename InputIt1, typename InputIt2, typename Compare, typename Func>
void MySetIntersection(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
Compare comp, Func func)
{
while (first1 != last1 && first2 != last2) {
if (comp(*first1, *first2))
++first1;
else if (comp(*first2, *first1))
++first2;
else
func(*first1++, *first2++);
}
}
看起来像是手动实现了一个合并。我以为有更优雅的东西。。。就像一个STL的一个班轮。当然,最后一行不是应该是func*first1++、*first2++?是的,我在最后一分钟重新安排了事情,制造了一个bug。我看到你详细阐述了你的答案,所以很遗憾我的答案被接受了+给你的。
template<typename InputIt1, typename InputIt2, typename Compare, typename Func>
void MySetIntersection(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
Compare comp, Func func)
{
while (first1 != last1 && first2 != last2) {
if (comp(*first1, *first2))
++first1;
else if (comp(*first2, *first1))
++first2;
else
func(*first1++, *first2++);
}
}