I am using unordered map like
unorderedmap.insert(make_pair(5, 6));
How could I get the iterator for the position of the key (value 5)? Do I need to use find() again or could I some how get it from the return value?
Thanks.
Assuming you are using this unordered_map, the iterator is:
unorderedmap.insert(make_pair(5, 6)).first;
First of all unordered_map is not a standard container. But if you are using a unordered_map provided by the compiler which provides an API similar to this then it returns a pair of <iterator,bool>. The iterator part of the pair which can be accesses using .first will give you the location where the element got inserted (if it was inserted succesfully, this can be tested using the bool second).
This is taken from http://www.cplusplus.com/reference/stl/map/insert/
So as stated before, use the pair::first to get the iterator.
The first version returns a pair, with
its member pair::first set to an
iterator pointing to either the newly
inserted element or to the element
that already had its same value in the
map. The pair::second element in the
pair is set to true if a new element
was inserted or false if an element
with the same value existed.
The unordered_map interface is similar to the set interface or the map interface in that the insert method returns a std::pair<iterator,bool>:
the bool is true if the insertion took place, it did not take place if an element with a similar key already existed in the container
the iterator points to the right element: either the already existing one or the newly inserted one depending on the case
Therefore, if you only wish to access the element, you can simply use:
map.insert(std::make_pair(key,value)).first
However do check that you do not need to know if the insert was successful or not, in general one care about it :)
Related
I am aware of the .find() method to check whether or not an element exists in a map. But suppose i have a map -- map -- with about 2000 elements and I want to add an element to the list. I first have to check if the element exists. Isn't it a bit inefficient to use .find() because the iterator has to 'iterate' over element in the map? Is there a more efficient and less time consuming way to check whether or not an element exists in a map?
std::map has logarithmic look-up complexity, so you won't have to visit all the elements to determine whether an element is in the map.
On the other hand, you can make the look-up and insert operation more concise by using std::map::emplace or std::map::insert:
auto [iter, ok] = the_map.emplace(the_key, a_value);
if (ok) {
// element was not in map so got inserted
}
This assumes that a_value either already exists, or that it is not an issue to construct it even if it does not end up being inserted into the map.
If you really need to use 'find and insert' idiom (and that could be because you can't construct a value object for the same key twice under any circumstances) and you are concerned about twice logarithmic complexity, you'd have to use std::map::equal_range.
The way to do this would be first use equal_range with your key, and than use one of returned iterators as a hint to insert.
I'd like to use the find() method, to catch a particular element of my std::map()
Now the return value is either the element I was looking for, or it it points to the end of the map if the element hasn't been found (C.f.: http://www.cplusplus.com/reference/map/map/find/ ).
So I'm using these two information whether to decide if an element is in the map or not. But what happens if the element is already inside but at the very end ? My if-query would then decide that it's not existing and therefor my program will be made up.
Am I getting this routine right, and if, how to prevent it ?
Thanks for your support
The last element in any container is not the same as the containers end iterator. The end iterator is actually one step beyond the last element in the container.
That means you can rest easily, and use find without worries. If the element you look for is the last element, you will get what you search for.
You can actually use if(!map.count(elem)) to check whether elem is present in the map, count() returns 0 if elem is not present in the map while find() returns an iterator which has to been compared to the end iterator, i.e., if(map.find(elem) != map.end()).
I'd like to use the find() method, to catch a particular element of my std::map()
Now the return value is either the element I was looking for, or it it points to the end of the map if the element hasn't been found (C.f.: http://www.cplusplus.com/reference/map/map/find/ ).
So I'm using these two information whether to decide if an element is in the map or not. But what happens if the element is already inside but at the very end ? My if-query would then decide that it's not existing and therefor my program will be made up.
Am I getting this routine right, and if, how to prevent it ?
Thanks for your support
The last element in any container is not the same as the containers end iterator. The end iterator is actually one step beyond the last element in the container.
That means you can rest easily, and use find without worries. If the element you look for is the last element, you will get what you search for.
You can actually use if(!map.count(elem)) to check whether elem is present in the map, count() returns 0 if elem is not present in the map while find() returns an iterator which has to been compared to the end iterator, i.e., if(map.find(elem) != map.end()).
I have the following C++ map example code:
map<string,string> &weight2price
....
weight = ...
price = ...
if(weight2price.find(weight) == weight2price.end())
weight2price[weight] = price;
could anyone tell me what it means by
if(weight2price.find(weight) == weight2price.end())
The STL Map is a standard C++ container. It uses unique keys that can be compared to refer to value data being stored inside the container. It works much like an array but unlike an array, the key can be anything and doesn't need to be an integer.
The syntax for a map is:
std::map < Key, Data, Compare, Alloc>
Key - the type of object that will be used as key
Data - the type of object that will be used as data
Compare - a comparison function for the keys
Alloc - The map's allocator, used for all internal memory management
usage:
map[Key] = Data
For further reading about STL maps look here :
http://en.wikipedia.org/wiki/Map_%28C%2B%2B%29
and here: http://www.sgi.com/tech/stl/Map.html
In the code snippet, you are using the function find() from the map. This function returns an iterator pointing to the element from the map that contains the key you were searching for. If that key is not found, the find function will return the iterator pointing to the end of the map. That is what is being checked in the code snippet you attached to your question and if the find function returned the value of the end iterator, this means that the key is not in the map, so it adds the key and data to the map. An optimization for your code was provided by GMan in his comment.
A very basic explanation for an iterator (although not complete) would be that an iterator is a pointer to a pair< Key,Data>.
Hope this helps!
If the key passed to find() does not exist, find() returns end(). So it's saying "If it wasn't found...".
The code could be written better as:
weight2price.insert(std::make_pair(weight, price));
So look-up isn't done twice. (If the key already exists, insert won't do anything.)
It means that weight was not found. Then if it wasn't found, it adds it.
map in C++ is a like hashmap, where a key (in your case weight) is mapped to a value (price).
Here it checks to see if the particular weight is already mapped in this map, if not the find method will return weight2price.end()
In that case the program enters a key-value pair in the map with the line that you greyed out.
I would like to ask if there is any point of checking if element exists in unorderd_set before inserting it? According to documentation:
Each element is inserted only if it is not equivalent to any other element already in the container (elements in an unordered_set have unique values).
So if I'm getting it correctly in my case:
Element *element = new Element;
//...
if ( my_set.find (element) == my_set.end() )
my_set.insert(element);
It is not required - correct? What actually happens if I try to insert element that is already in the set. Does it do exactly the same check that I am doing?
If you try to insert a value that is already present, the set will remain unchanged. The call will return a pair containing an iterator and Boolean. The Boolean will be false if the item was already present.
http://en.cppreference.com/w/cpp/container/unordered_set/insert
Note that in your case where the set contains pointers it will only prevent you from having duplicate pointers, not duplicate contents. For example,
if your Element object represented an element, like Oxygen, it might contain a value for the atomic number and a string for the name. If you only want oxygen to appear once, a set of pointers will not automatically do this.
An insert() on unorderd_set does a find() to see if the object exists and then inserts the object.
So in your code they are two find(), one explicit, and other inside the insert()