簡體   English   中英

如何為std :: multimap的給定鍵獲取“previous”項的迭代器(或值)?

[英]How to get the iterator (or the value) for “previous” item for given key of std::multimap?

對於我的std::multimap ,我想獲得給定鍵之前的項目。

對於在給定鍵之后的項目,我可以簡單地使用std::multimap::upper_bound (它將返回鍵大於給定的元素)。 但不幸的是, std::multimap::lower_bound返回帶有“lower 或equal ”鍵的元素。

樣本取自http://www.cplusplus.com/reference/map/multimap/lower_bound/

mymultimap.insert(std::make_pair('a',10));
mymultimap.insert(std::make_pair('b',121));
mymultimap.insert(std::make_pair('c',1001));
mymultimap.insert(std::make_pair('c',2002));
mymultimap.insert(std::make_pair('d',11011));
mymultimap.insert(std::make_pair('e',44));

itlow = mymultimap.lower_bound ('b');  // itlow points to b
itup = mymultimap.upper_bound ('d');   // itup points to e (not d)

如何獲得迭代器(或價值), a當你給b作為參數?

你可以使用lower_bound ,但是你必須考慮兩個邊緣情況:它返回begin()並返回end()

auto itfound = mymultimap.lower_bound('b');
if (itfound == mymultimap.begin()) {
    // 'b', or something past 'b', is the first item
    // or the map is empty
    // what to do here?
}
else if (itfound == mymultimap.end()) {
    // there does not exist an item >= 'b'
    // what to do here? possibly std::prev(end()) ?
}
else {
    // ok cool, we found something in the middle
    // just back up
    --itfound;

    // do stuff with itfound here
}

繼續使用lower_bound ,然后遞減你收到的迭代器(在檢查之后確保它沒有begin )。

itfound = mymultimap.lower_bound('b');
if (itfound != mymultimap.begin())
{
    --itfound;
    // do something with itfound
}

如果項目不在地圖中,您可能需要稍微不同的邏輯,但這不應該是一個很難修改。

我們知道以下內容對於任何有序的容器(即mapsetmultimapmultiset ):

  • lower_bound(key)返回第一個條目> = key
  • upper_bound(key)返回第一個條目> key

如果沒有條目> = /> key每個函數也返回end()

所以我們有基於運算符>和> =的功能。 我們可能會合理地問,我們是否可以基於<和<=的功能?

要求第一個條目<或<= key (這是容器中的begin()或者不是begin()這有點微不足道。 然而,要求最后這樣的條目是有意義的。 實際上,你要求的最后一個條目< key
為了完整起見,我們將考慮最后一個條目<= key

我們假設我們有這樣的功能,如果沒有這樣的條目它們應該怎么做? 我們可以比返回end()做得更糟糕 - 它是一個可測試的值,與任何成功案例都不同。 它還與lower_boundupper_bound以及<algorithm>標頭中的find和一大堆獨立搜索功能一致。 底線是end()通常用於表示“沒有這樣的條目”,所以這對我們來說也應該足夠好。

正如Barry和Mark所說,調用lower_bound(key)然后遞減將給我們想要的東西,除非lower_bound(key) == begin() 在這種情況下,第一個(因此[joint-]最小的)條目是> = key ,所以沒有條目< key - 正是我們剛才說的應該返回end()

對於查找最后一個條目<= key我們可以使用upper_bound ,當upper_bound(key) == begin()時,再次返回end()以表示'no such entry'。

讓我們分別調用這些函數lower_bound_decupper_bound_dec

// Find the last entry < key, returning end() if all entries are >= key
// Container can be any that implements lower_bound, e.g. std::map, std::multimap, std::set or std::multiset
template<typename Container, typename Key>
typename Container::const_iterator lower_bound_dec(const Container &container, const Key &key) {
    auto it = container.lower_bound(key);
    if (it == std::begin(container))
        it = std::end(container);
    else
        --it;
    return it;
}

// Find the last entry <= key, returning end() if all entries are > key
// Container can be any that implements upper_bound, e.g. std::map, std::multimap, std::set or std::multiset
template<typename Container, typename Key>
typename Container::const_iterator upper_bound_dec(const Container &container, const Key &key) {
    auto it = container.upper_bound(key);
    if (it == std::begin(container))
        it = std::end(container);
    else
        --it;
    return it;
}

我們還可以定義基於迭代器的函數,鏡像std::lower_boundstd::upper_bound並且可以使用雙向迭代器對任何已排序的范圍進行操作:

// Find the last entry < key, returning end() if all entries are >= key
// last must be reachable from first, and all entries in sorted order between them
template<typename Iterator, typename Key>
Iterator lower_bound_dec(Iterator first, Iterator last, const Key &key) {
    auto it = container.lower_bound(first, last, key);
    if (it == first)
        it = last;
    else
        --it; // requires bidirectional iterators
    return it;
}

upper_bound(first, last, key)以及將比較器留給upper_bound(first, last, key)的形式給讀者/任何想通過編輯獲得代表的人! :)

TL / DR:使用lower_bound然后遞減,但需要注意“遞減” begin()產生end()以表示“沒有這樣的條目”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM