比较std::对的2个std::列表

Comparing 2 std::lists of std::pairs

本文关键字:std 列表 2个 对的 比较      更新时间:2023-10-16

我希望你能在这里帮我。我已经搜索了其他答案,但没有找到符合我具体情况的答案(但如果你找到了,请告诉我网址!)。我看到了很多关于使用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("rn");
}
it1++;
it2 = outputList2.begin();
}
it2++;
if (it2 == outputList2.end())
it1++;
}

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

谢谢大家!

根据我对问题的理解,
您希望将一个列表中的每个元素与另一个列表的其他元素进行比较
您可以使用一对基于嵌套范围的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
}
}
}

答案使用辅助映射,但请记住,如果使用两个映射(或哈希表)而不是两个列表,则会得到更好的结果。

// 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
}
}

您可以使用带有先决条件的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);
}

如果列表中的键的顺序与示例中的相同,则可以线性遍历列表:

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;
}