我有2个对列表,每个列表都有匹配对,非匹配对和唯一对。我想保留唯一和不匹配的对。
我制作了这段代码,它非常适合查找不匹配,但不是唯一的:
std::list <std::pair<std::string,std::string>> outputList1;
std::list <std::pair<std::string,std::string>> outputList2;
for (auto x: outputList1){
for (auto y: outputList2){
//compare x to y
if(x.first == y.first)
{
if(x.second != y.second)
{
//mismatch on the second element
//do something with it
}
}
}
}
这就是我试图引入的独特之处。我试图检查我是否在y的最后一个元素,如果是这样,保存该对以拉出独特的元素,但它正在拉动所有内容。我试着把它写在纸上,但是我的头在旋转。
auto &last = *(--outputList2.end());
for (auto x: outputList1){
for (auto& y: outputList2){
//compare x to y
if(x.first == y.first)
{
if(x.second != y.second)
{
//mistmatch found so I save it off somewhere
}
}
else if(&y == &last)
{
//unique item found in list x
}
}
}
我还尝试过这个,以便在其他地方结束y:
else if(&y == &*std::prev(std::end(outputList2)))
你能看出我做错了吗?
答案 0 :(得分:2)
我认为你搜索std::set_symmetric_difference
。换句话说,您希望对除两个列表中存在的元素(匹配的元素)之外的所有元素执行某些操作。换句话说,您想要丢弃交叉点。这就是构建std::set_symmetric_difference
的原因。
包含std::set_difference
和std::set_symmetric_difference
的内容必须对范围进行排序。因此,我们首先对列表进行排序,但是在另一个列表中保持原始列表不变,并使用引用包装器来避免内部对的这么多副本,对这些对的引用进行排序。由于std::reference_wrapper
没有定义operator<
,我们需要传递比较器(lambda函数):
#include <iostream>
#include <algorithm>
#include <iterator>
#include <list>
#include <functional>
using pair_t = std::pair<std::string, std::string>;
using pair_cref = std::reference_wrapper<const pair_t>;
int main()
{
std::list<pair_t> outputList1{{"c", "b"}, {"a", "g"}, {"0", "f"}};
std::list<pair_t> outputList2{{"c", "d"}, {"0", "f"}, {"z", "1"}};
std::list<pair_cref> sorted_view_1(outputList1.begin(), outputList1.end());
std::list<pair_cref> sorted_view_2(outputList2.begin(), outputList2.end());
auto less_f = [](const pair_cref& a, const pair_cref& b)
{ return a.get() < b.get(); };
sorted_view_1.sort(less_f);
sorted_view_2.sort(less_f);
std::list<pair_cref> unmatchs_and_uniques;
std::set_symmetric_difference(sorted_view_1.begin(), sorted_view_1.end(),
sorted_view_2.begin(), sorted_view_2.end(),
std::back_inserter(unmatchs_and_uniques), less_f);
for (const auto& p : unmatchs_and_uniques)
std::cout << p.get().first << ", " << p.get().second << std::endl;
}
输出:
a, g
c, b
c, d
z, 1
Coliru demo。
如果您不介意修改原始列表,您可以这样做:
outputList1.sort();
outputList2.sort();
而不是创建已排序的视图,并直接在std::set_symmetric_difference
上应用outputListx
。
代码更具可读性,但不会更短。在任何情况下,该解决方案都更快,因为您的解决方案
复杂性顺序,在使用std::list::sort
和std::set_symmetric_difference
时,算法的复杂性顺序是sort()
(std::set_symmetric_difference
具有线性顺序)之一:
nx
最长列表的大小。