Checking if element exists in unorderd_set before inserting it - c++

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()

Related

c++ Should I compare the last element of a list to my val when I am running find algorithm? [duplicate]

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()).

Does find() also return the last element of a map in C++?

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()).

Difficulty with map of map deletion

How do you delete the first element of the inner map of a map of a map?
I've tried doing something like
my_map[here].erase(my_map[here].begin())
but I'm getting unexpected results. Any suggestions or resources would be great.
Does my_map[here] actually exist?
You may want to find it, i.e.
if((auto it = my_map.find(here)) != my_map.end()) {
it->erase(it->begin());
}
If my_map[here] didn't exist when you tried to access it, a new element will be created there:
http://www.cplusplus.com/reference/map/map/operator%5B%5D/
If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value. Notice that this always increases the container size by one, even if no mapped value is assigned to the element (the element is constructed using its default constructor).
To prevent this, you can use the find function as I have indicated above.
find searches for the element with the specified key. If it finds something, it will return the iterator to that element. Otherwise, it will return my_map.end(), which is NOT the last element but a special iterator signifying the end of the structure.

How to change a set element?

I want to change the element in a set, so I used set<T>::iterator. However, the compiler argues "the element is const". Then I realized that set<T>::iterator is a const_iterator...
So, how I can change the element? Erase it and then insert a new one?
The elements of the set will be in sorted order. If you are allowed to modify an element, then this sorting order can not be maintained. Hence you can not modify the item. You need to erase the existing element and insert a new one.
Set elements are constant and may not be modified in place. Modification could change the ordering predicate without changing the position of the element which would violate the constraints of the data structure.
However now in the future (C++17), modifying the element without erasure is possible with the extract member function:
std::set<std::string> stringset{"a", "b", "c"};
auto node = stringset.extract(stringset.begin());
std::string& str = node.value();
str = "d";
stringset.insert(std::move(node));
There is still the cost of list operations but the object itself is not destroyed or copied.
EDIT: You cant add an element to a specific location in set. the set should be in the sorted order whatever operations you do. So you have to erase the specific element and insert the new element so that the ordering of set isnt lost.
Also read more about set!

unordered_map C++

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 :)