2016-05-31 129 views
0

我希望你能幫助我。我已經搜索了其他答案,但我還沒有找到符合我的具體情況的東西(但是如果您確實找到了一個答案,請讓我知道網址!)。我看到很多關於使用std :: map而不是list的建議,我不介意在需要時切換容器。比較2 std :: std ::對列表

目前,我有對兩個列表即

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

我已填充與我已經從SQL數據庫(I省略這裏的SQL檢索代碼)檢索用戶設置每一個清單。

實施例列表:

outputList1(第一,第二)
CanSeeAll,真
CanSubmit,假
CanControl,假

OutputList2:
CanSeeAll,假
CanSubmit,真
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++; 
} 

我知道這個邏輯是有缺陷的,因爲它會在第一次迭代後,跳過第二個名單上的第一對,但這是目前我能想到的最好的,當下我正在敲鍵盤。

謝謝大家!

+0

這兩個列表是否包含相同的第一對?如同,如果你將列表結合在一起,每個設置都會有2個? – user975989

+0

如果列表中的任何一個包含多個具有相同「第一個」值的'std :: pair',您預期會發生什麼? –

+0

這兩個列表是否總是包含相同的密鑰? – Oebele

回答

0

據我所知,問題
你想比較一個列表的每個元素,到另一個列表的每個其他元素。
您可以使用一對基於循環的嵌套範圍。

#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 
    } 
    } 
} 
+0

如果你使用'map',而不是'O(n^2)',你可以在'O(n)'中完成。 – user975989

+0

@ user975989是的,如果效率問題,OP肯定會考慮另一種數據結構。 –

+0

@Trevor謝謝特雷弗我覺得這對我有效!我嘗試了幾種不同的樣本大小和不同的設置,它似乎是隨地吐痰的不匹配! – Behuvius

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 
    } 
} 
+0

我沒有看到它在哪裏迭代List2(使用它)。看起來它只是迭代List 1,比較第一對List 2.我錯過了什麼嗎?我不使用汽車很多,但我們不需要一個++它在什麼地方走過List2? – Behuvius

+0

在l2上的迭代已經完成(在開始時),從這一點開始,您只需要在地圖上查找相應的元素。我已更新我的答案,以刪除汽車並添加更多評論。 –

+0

大聲笑是的,我看到你編輯後的迭代:) – Behuvius

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