比较std :: pairs

时间:2016-05-31 02:45:31

标签: c++

我希望你能在这里帮助我。我已经搜索了其他答案,但我找不到符合我具体情况的东西(但如果找到了,请告诉我这个URL!)。我已经看到很多关于使用std :: map而不是list的建议,如果需要,我不介意切换容器。

目前,我有两对配对,即

 std:list <std::pair<string,string>> outputList1; 
 std:list <std::pair<string,string>> outputList2;

我已经使用从SQL数据库检索到的用户设置填充了每个列表(我在此省略了SQL检索代码)。

示例列表:

outputList1(第一,第二)
  CanSeeAll,True
  CanSubmit,False
  CanControl,False

OutputList2:
CanSeeAll,False
CanSubmit,True
CanControl,False

我想遍历两个列表并找到不匹配。例如,找到第一个列表的第一对中的第一个字符串以在第二个列表中找到匹配的第一个字符串,然后比较第二个字符串以确定它们是否匹配,然后将非匹配对打印出来到新字符串(最终提交),等等。

在这个例子中,最后一个字符串将CanSeeAll和CanSubmit作为最终输出,因为那些是不匹配的两个。

这是我到目前为止所尝试的内容,但我得到一个空白字符串:

std::list <std::pair<std::string,std::string>>::iterator it1 = outputList1.begin();
std::list <std::pair<std::string,std::string>>::iterator it2 = outputList2.begin();

string token;

while (it1 != outputList1.end()){

if((*it1).first == ((*it2).first))
 {
           if((*it1).second != ((*it2).second))
           {
                token.append((*it1).first);
                token.append(",");
                token.append((*it1).second);
                token.append("\r\n");
            }
            it1++;
            it2 = outputList2.begin();
 }
              it2++;
          if (it2 == outputList2.end())
              it1++;
}

我知道这个逻辑是有缺陷的,因为它会在第一次迭代后跳过第二个列表上的第一对,但这是我现在能想到的最好的,我正在敲击键盘上的一个时刻。

谢谢大家!

4 个答案:

答案 0 :(得分:0)

据我了解这个问题,
您想要将一个列表的每个元素与另一个列表中的每个其他元素进行比较 您可以使用一对基于for循环的嵌套范围。

#include <list>
#include <string>

int main(){
  std::list<std::pair<std::string,std::string>> l1;
  std::list<std::pair<std::string,std::string>> l2;

  for (auto x: l1){
    for (auto y: l2){
      //compare x to y
    }
  }
}

答案 1 :(得分:0)

答案使用辅助地图但是,请注意,如果使用两个地图(或哈希表)而不是两个列表,您将获得更好的结果。

// create a map for elements in l2
std::map<std::string, std::string> l2map;

// move elements from l2 to the map so we get O(N*log(N)) instead of O(n²)
for (std::list<std::pair<std::string,std::string> >::iterator it = l2.begin();
     it != l2.end(); 
     ++it) 
{
    l2map.insert(*it);
}

// walk l1 and look in l2map
for (std::list<std::pair<std::string,std::string> >::iterator l1it = l1.begin();
     l1it != l1.end(); 
     ++l1it)
{
    // look for the element with the same key in l2
    // l1it->first is the key form l1
    std::map<std::string, std::string>::iterator l2it = l2map.find(l1it->first);

    if (l2it != l2map.end()) {
        // found, then compare
        if (l1it->second != l2it->second) { // l1it->second is the value from l1
            // mismatch
        }
    } else {
        // not in l2
    }
}

答案 2 :(得分:0)

您可以在前提条件下使用std::mismatch:所有设置在两个列表中以相同的顺序发生(如果不是这样,您可以进行排序)

auto iterPair = std::mismatch(l1.begin(), l1.end(), l2.begin());
while (iterPair.first != l1.end()) {
     // TODO: Handle the mismatching iterators
     iterPair = std::mismatch(iterPair.first + 1, l1.end(), iterPair.second + 1);
}

答案 3 :(得分:0)

如果列表中的键具有相同的顺序(如示例所示),则可以线性遍历列表:

std::ostringstream s;
std:list<std::pair<string, string>>::const_iterator i2(outputList2.cbegin());
for(auto const &pair: outputList1) {
    if(pair.second != i2->second) {
        s << pair.first << ": " << pair.second << " != " << i2->second << endl;
    }
    ++i2;
}

或者,使用STL算法:

#include <algorithm>

typedef std::list<std::pair<std::string, std::string>> List;
std::ostringstream s;
for(
    auto itrs(
        std::mismatch(
            outputList1.cbegin(), outputList1.cend(), outputList2.cbegin()
            , [](auto const &l, auto const &r){ return l.second == r.second; }))
    ; itrs.first != outputList1.cend()
    ; itrs = std::mismatch(itrs.first, outputList1.cend(), itrs.second
                 , [](auto const &l, auto const &r){ return l.second == r.second; }))
{
    s << itrs.first->first << ": "
        << itrs.first->second << " != " << itrs.second->second
        << std::endl;
}