比较std :: pairs的2个std ::列表 - 保持唯一和不同的元素

时间:2016-10-28 22:16:55

标签: c++ c++11

我有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)))

你能看出我做错了吗?

1 个答案:

答案 0 :(得分:2)

我认为你搜索std::set_symmetric_difference。换句话说,您希望对除两个列表中存在的元素(匹配的元素)之外的所有元素执行某些操作。换句话说,您想要丢弃交叉点。这就是构建std::set_symmetric_difference的原因。

包含std::set_differencestd::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

代码更具可读性,但不会更短。在任何情况下,该解决方案都更快,因为您的解决方案

yours

复杂性顺序,在使用std::list::sortstd::set_symmetric_difference时,算法的复杂性顺序是sort()std::set_symmetric_difference具有线性顺序)之一:

mine

nx最长列表的大小。