2011-09-07 34 views
5

我使用的是C++ std::multimap,我必須遍歷兩個不同的鍵。有沒有一種有效的方式來做到這一點,而不是創建兩個範圍並單獨循環這些範圍?std :: multimap獲取兩個範圍

這是即時通訊的方式做現在:

std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range; 
std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range2; 

// get the range of String key 
range = multimap.equal_range(key1); 
range2 = multimap.equal_range(key2); 

for (std::multimap<String, Object*>::iterator it = range.first; it != range.second; ++it) 
{ 
    ... 
} 
for (std::multimap<String, Object*>::iterator it2 = range2.first; it2 != range2.second; ++it2) 
{ 
    ... 
} 
+2

你爲什麼覺得效率不高? –

+0

這是我第一次使用multimap,所以我不太熟悉它們。我會在這些循環中做很多工作,我想知道是否有另一種操作可以在同一時間或兩者之間獲得兩個範圍。 –

+0

你可以給出一個鑰匙重疊的例子,但不相等嗎?也許我的大腦是溼漉漉的,但它似乎是一個簡單的平等檢查的關鍵會做到這一點。對於每個查詢,如果您有單獨的上限和下限,對我來說更有意義。 –

回答

3

您開始使用的代碼是最直接的。

如果您確實想在同一個循環中迭代兩個範圍,您可以創建一個自定義迭代器,該迭代器需要兩個迭代器範圍,迭代第一個範圍,直到完成,然後切換到第二個迭代器範圍。這可能比它的價值更麻煩,因爲你需要自己實現所有的迭代器成員。

編輯:我正在反思這個;只需將兩個循環修改爲一個循環就很簡單。

for (std::multimap<String, Object*>::iterator it = range.first; it != range2.second; ++it) 
{ 
    if (it == range.second) 
    { 
     it = range2.first; 
     if (it == range2.second) 
      break; 
    } 
    ... 
} 
+0

我想到了這一點。但是,這兩個鍵必須彼此相鄰才能工作?例如,如果我有3個鍵,我想循環第一和第三不會包含第二個與他們?或者做那些如果陳述修復? –

+1

@Kaiser,'if'語句處理從第一個範圍到第二個範圍的轉換。他們甚至可能失靈。他們*不能做的唯一事情就是相交;如果'range2'包含'range.second',那麼你會得到一個無限循環。 –

+0

啊,我明白了。我的範圍2是靜態的,範圍1總是會有所不同。他們不應該相交正確?由於multimap在插入時對它進行排序? –

3

當然,Boost會這樣做。使用Boost.Range和它的join函數會得到你想要的。有關更多詳細信息,請參見Boost Range Library: Traversing Two Ranges Sequentially

+0

謝謝,Boost似乎真的很強大。不幸的是,我的公司是老派,不喜歡新的東西......我猜他們必須要解決效率低下問題 –

+0

這不是關於效率,而是關於便利性 –

0

如果你有機會到C++ - 11(Visual Studio的10+,GCC-4.5 +),並允許使用它auto是一個真正的寶石:

// get the range of String key 
auto range = multimap.equal_range(key1); 
auto range2 = multimap.equal_range(key2); 

for (auto it = range.first; it != range.second; ++it) 
{ 
    ... 
} 
for (auto it2 = range2.first; it2 != range2.second; ++it2) 
{ 
    ... 
} 

無論如何,我只想測試鍵只有在key2!= key1的情況下才執行第二個循環。每次在循環中檢查迭代器都會產生一定的代價。

來自第二個範圍的std :: set_difference可能簡化代碼。 也許std :: set_union這兩個範圍,並通過back_inserter插入到一個集,所以你只能得到一個副本?

一些實驗可能是有序的。不要忘記在混音中加入你的第一個猜測。在速度方面,它可能會讓你感到驚訝。除非範圍通常非常長,並且/或者循環操作昂貴,否則可能不值得額外記賬。