[英]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
}
如果项目不在地图中,您可能需要稍微不同的逻辑,但这不应该是一个很难修改。
我们知道以下内容对于任何有序的容器(即map
, set
, multimap
和multiset
):
lower_bound(key)
返回第一个条目> = key
upper_bound(key)
返回第一个条目> key
如果没有条目> = /> key
每个函数也返回end()
。
所以我们有基于运算符>和> =的功能。 我们可能会合理地问,我们是否可以基于<和<=的功能?
要求第一个条目<或<= key
(这是容器中的begin()
或者不是begin()
这有点微不足道。 然而,要求最后这样的条目是有意义的。 实际上,你要求的是最后一个条目< key
。
为了完整起见,我们将考虑最后一个条目<= key
。
我们假设我们有这样的功能,如果没有这样的条目它们应该怎么做? 我们可以比返回end()
做得更糟糕 - 它是一个可测试的值,与任何成功案例都不同。 它还与lower_bound
, upper_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_dec
和upper_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_bound
和std::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.