Reputation: 4946
How to get the last element of an std::unordered_map
?
myMap.rbegin()
and --myMap.end()
are not possible.
Upvotes: 13
Views: 17851
Reputation: 33
It may not be the best solution, performance-wise, but in C++11 and later, I use a combination of std::next()
and size()
to jump all elements from the beginning of the map, as shown below:
std::unordered_map<int,std::string> mapX;
...
if (mapX.size() > 0) {
std::unordered_map<int,std::string>::iterator itLast =
std::next(mapX.begin(), mapX.size() - 1);
...
Upvotes: 0
Reputation: 6891
The accepted answer seems wrong. Unordered_map does have the last element even though the key-value pair is not stored in sorted order. Since the iterator of unorered_map is forwar_iterator(LegacyForwardIterator), the cost to find the last element is O(n). Yakk - Adam gave the correct answer. Essentially, you have to iterator the container from begin to end. At each iteration, you have to check whether the next element is end(); if yes then you are at the last element.
You cannot call prev(it) or --it. There will be no syntax error, but you will have a runtime error (more likely segmentation fault) when using the prev(it) or --it. Maybe next version of compiler can tell you that you have an logic error.
Upvotes: 0
Reputation: 510
.end()
is an iterator to the "element past the last element". That's why you compare it like this when you loop through a map:
for (auto it = myMap.begin(); it != myMap.end(); ++it) // '!=' operator here makes it possible to only work with valid elements
{
}
So you want the "last" element (whatever that may be, because it's not really guaranteed to be the last in an unordered map, since it ultimately depends on how the key was hashed and in which "bucket" it ends up in). Then you need: --myMap.end()
More specifically, .end()
is a function, that returns an iterator, same as .begin()
returns an iterator. Since there is no .rbegin()
in an std::unordered_map
, you have to use --
(the decrement operator):
auto it = --myMap.end();
To access the key you use it->first
, to access the value you use it->second
.
Upvotes: 1
Reputation: 23793
There is no "last element" in a container that is unordered.
You might want an ordered container, e.g. std::map
and access the last element with mymap.rbegin()->first
(Also see this post)
EDIT:
To check if your iterator is going to hit the end, simply increment it (and possibly save it in a temporary) and check it against mymap.end()
, or, even cleaner : if (std::next(it) == last)
Upvotes: 14
Reputation: 275405
In your comments, it appears your goal is to determine if you are on the last element when iterating forward. This is a far easier problem to solve than finding the last element:
template<class Range, class Iterator>
bool is_last_element_of( Range const& r, Iterator&& it ) {
using std::end;
if (it == end(r)) return false;
if (std::next(std::forward<Iterator>(it)) == end(r)) return true;
return false;
}
the above should work on any iterable Range (including arrays, std
containers, or custom containers).
We check if we are end
(in which case, we aren't the last element, and advancing would be illegal).
If we aren't end
, we see if std::next
of us is end
. If so, we are the last element.
Otherwise, we are not.
This will not work on iterators that do not support multiple passes.
Upvotes: 2
Reputation: 9270
std::unordered_map::iterator last_elem;
for (std::unordered_map::iterator iter = myMap.begin(); iter != myMap.end(); iter++)
last_elem = iter;
// use last_elem, which now points to the last element in the map
This will give you the last element in whatever order the map gives them to you.
Edit: You need to use std::unordered_map<YourKeyType, YourValueType>
instead of just std::unordered_map
. I just wrote it like this because you did not provide the type in your question.
Alternatively, as suggested by vsoftco
(thanks), you could declare both last_elem
and iter
as decltype(myMap)::iterator
.
(If you're compiling with the MSVC++ compiler, then you will need to add typedef decltype(myMap) map_type;
and then instead of decltype(myMap)::iterator
use map_type::iterator
.)
Upvotes: 1
Reputation:
You cant. by definition, the element is not stored based on some sort of order. the key is hashed first and that's why O(1) search is possible. if you wanna check whether a key exists in the unordered_map or not, u can use this code:
std::unordered_map dico;
if(dico.count(key)!=0){
//code here
}
Upvotes: 1