STL MAP should use find() or [n] identifier to find element in map?
Using find
means that you don't inadvertently create a new element in the map if the key doesn't exist, and -- more importantly -- this means that you can use find
to look up an element if all you have is a constant reference to the map.
That of course means that you should check the return value of find
. Typically it goes like this:
void somewhere(const std::map<K, T> & mymap, K const & key)
{
auto it = mymap.find(key);
if (it == mymap.end()) { /* not found! */ }
else { do_something_with(it->second); }
}
When I should use std::map::at to retrieve map element
Contrary to most existing answers here, note that there are actually 4 methods related to finding an element in a map (ignoring lower_bound
, upper_bound
and equal_range
, which are less precise):
operator[]
only exist in non-const version, as noted it will create the element if it does not existat()
, introduced in C++11, returns a reference to the element if it exists and throws an exception otherwisefind()
returns an iterator to the element if it exists or an iterator tomap::end()
if it does notcount()
returns the number of such elements, in amap
, this is 0 or 1
Now that the semantics are clear, let us review when to use which:
- if you only wish to know whether an element is present in the
map
(or not), then usecount()
. - if you wish to access the element, and it shall be in the
map
, then useat()
. - if you wish to access the element, and do not know whether it is in the
map
or not, then usefind()
; do not forget to check that the resulting iterator is not equal to the result ofend()
. - finally, if you wish to access the element if it exists or create it (and access it) if it does not, use
operator[]
; if you do not wish to call the type default constructor to create it, then use eitherinsert
oremplace
appropriately
Determine if map contains a value for a key?
Does something along these lines exist?
No. With the stl map class, you use ::find()
to search the map, and compare the returned iterator to std::map::end()
so
map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}
Obviously you can write your own getValue()
routine if you want (also in C++, there is no reason to use out
), but I would suspect that once you get the hang of using std::map::find()
you won't want to waste your time.
Also your code is slightly wrong:
m.find('2');
will search the map for a keyvalue that is '2'
. IIRC the C++ compiler will implicitly convert '2' to an int, which results in the numeric value for the ASCII code for '2' which is not what you want.
Since your keytype in this example is int
you want to search like this: m.find(2);
How to find an element in std::map with structures that has at least one data member equal to the key
std::map
is defined only in terms of the operator<
. Two map entries are considered equal if and only if !(a < b)
and !(b < a)
. Your operator==
is not helping here, and all the find()
call is doing is finding the person with the ID you specified (or name in the second case) because it only considers operator<
.
The bigger picture is that std::map::find
makes use of the sortedness of std::map
(generally implemented as a red black tree) to avoid having to check each element. This property is not helpful if both name and ID participate in your search, because you can't tell if a matching name or is before or after any given node in the tree - you only know that for the ID (or, in the second case, the name).
Unless you want to implement a very fancy and complex way of combining the name and ID into a single sortable/searchable field (no idea how you would do that), you will have to check each element. std::find_if
does that for you:
std::find_if(phonebook.begin(), phonebook.end(), [name, id](const std::pair<Person, std::string>& personAndNumber) {
const Person& person = personAndNumber.first;
return person.name == name || person.id == id;
});
How to find if a given key exists in a C++ std::map
Use map::find
and map::end
:
if (m.find("f") == m.end()) {
// not found
} else {
// found
}
In STL maps, is it better to use map::insert than []?
When you write
map[key] = value;
there's no way to tell if you replaced the value
for key
, or if you created a new key
with value
.
map::insert()
will only create:
using std::cout; using std::endl;
typedef std::map<int, std::string> MyMap;
MyMap map;
// ...
std::pair<MyMap::iterator, bool> res = map.insert(MyMap::value_type(key,value));
if ( ! res.second ) {
cout << "key " << key << " already exists "
<< " with value " << (res.first)->second << endl;
} else {
cout << "created key " << key << " with value " << value << endl;
}
For most of my apps, I usually don't care if I'm creating or replacing, so I use the easier to read map[key] = value
.
Finding an element in map by its value
You can use the member function find
to search for key only. To search for a value, you can use a std::find_if
with a lambda function (if you use C++11), or to traverse the map (ok in previous C++ version):
for (HandleMap::const_iterator it = map.begin(); it != map.end(); ++it) {
if (it->second == name) return it->first;
}
// or value not found
On the other hand, if searching for a value is a very common operation, you may want to have two maps: std::unordered_map<Handle, std::string>
and std::unordered_map<std::string, Handle>
. In that case, you have to make sure you perform insertions, deletions, etc. in both maps to keep then synchronized.
STL set::find redefined search
If you have multiple elements with the same inner pair and a differing group id, you could use std::multimap<innerPair, int>
.
This allows you to store multiple elements with the same innerPair
.
It also simplifies searching with lower_bound/upper_bound
or equal_range
.
Related Topics
Overload Resolution and Arrays: Which Function Should Be Called
Qt "Private Slots:" What Is This
Should Accessors Return Values or Constant References
Reading and Writing to Usb (Hid) Interrupt Endpoints on MAC
Shift Image Content with Opencv
How to Be Notified of File/Directory Change in C/C++, Ideally Using Posix
Is There a Reason Why Not to Use Link-Time Optimization (Lto)
Getprocaddress Function in C++
Compile Program for 32Bit on 64Bit Linux Os Causes Fatal Error
Getting Std::Thread/Mutex to Work Under Win7 with Mingw and G++ 4.7.2
C++ Check If Statement Can Be Evaluated Constexpr
"Template<>" VS "Template" Without Brackets - What's the Difference
Is Using a Vector of Boolean Values Slower Than a Dynamic Bitset
How to Build Libcxx and Libcxxabi by Clang on Centos 7
Is There a Reason Declval Returns Add_Rvalue_Reference Instead of Add_Lvalue_Reference
Best Cross-Platform Method to Get Aligned Memory