Ответ 1
Используйте map::find
if ( m.find("f") == m.end() ) {
// not found
} else {
// found
}
Я пытаюсь проверить, находится ли данный ключ на карте, и несколько не может этого сделать:
typedef map<string,string>::iterator mi;
map<string, string> m;
m.insert(make_pair("f","++--"));
pair<mi,mi> p = m.equal_range("f");//I'm not sure if equal_range does what I want
cout << p.first;//I'm getting error here
так как я могу напечатать то, что находится в p?
Используйте map::find
if ( m.find("f") == m.end() ) {
// not found
} else {
// found
}
Чтобы проверить, существует ли конкретный ключ на карте, используйте функцию-член count
одним из следующих способов:
m.count(key) > 0
m.count(key) == 1
m.count(key) != 0
документация для map::find
говорит: "Другая функция-член, map::count
, может использоваться, чтобы просто проверить, существует ли конкретный ключ."
documentation для map::count
говорит:" Поскольку все элементы в контейнере карты уникальны, функция может возвращать только 1 (если элемент) или ноль (в противном случае).
Чтобы получить значение с карты с помощью ключа, который, как вы знаете, существует, используйте map:: at:
value = m.at(key)
В отличие от map:: operator [], map::at
не создаст новый ключ на карте, если указанный ключ не существует.
Вы можете использовать .find()
:
map<string,string>::iterator i = m.find("f");
if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }
С++ 20 дает нам std::map::contains
для этого.
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> example = {{1, "One"}, {2, "Two"},
{3, "Three"}, {42, "Don\'t Panic!!!"}};
if(example.contains(42)) {
std::cout << "Found\n";
} else {
std::cout << "Not found\n";
}
}
m.find == m.end() // not found
Если вы хотите использовать другой API, то найдите m.count(c)>0
if (m.count("f")>0)
cout << " is an element of m.\n";
else
cout << " is not an element of m.\n";
Я думаю, вы хотите map::find
. Если m.find("f")
равно m.end()
, ключ не был найден. В противном случае find возвращает итератор, указывающий на найденный элемент.
Ошибка связана с тем, что p.first
является итератором, который не работает для вставки потока. Измените свою последнюю строку на cout << (p.first)->first;
. p
- пара итераторов, p.first
- итератор, p.first->first
- ключевая строка.
В карте может быть только один элемент для заданного ключа, поэтому equal_range
не очень полезен. Он определен для карты, потому что он определен для всех ассоциативных контейнеров, но это намного интереснее для мультимапа.
map<string, string> m;
существует ключ проверки или нет, и возвращается число событий (0/1 в карте):
int num = m.count("f");
if (num>0) {
//found
} else {
// not found
}
существует ключ проверки или нет, и возвращает итератор:
map<string,string>::iterator mi = m.find("f");
if(mi != m.end()) {
//found
//do something to mi.
} else {
// not found
}
в вашем вопросе ошибка, вызванная плохой перегрузкой operator<<
, потому что p.first
- map<string, string>
, вы не можете ее распечатать. попробуй это:
if(p.first != p.second) {
cout << p.first->first << " " << p.first->second << endl;
}
template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
return (container.find(key) != std::end(container));
}
Конечно, если бы вы хотели получить fancier, вы всегда могли бы отформатировать функцию, которая также приняла найденную функцию и не найденную функцию, что-то вроде этого:
template <typename T, typename Key, typename FoundFunction, typename NotFoundFunction>
void find_and_execute(const T& container, const Key& key, FoundFunction found_function, NotFoundFunction not_found_function)
{
auto& it = container.find(key);
if (it != std::end(container))
{
found_function(key, it->second);
}
else
{
not_found_function(key);
}
}
И используйте его следующим образом:
std::map<int, int> some_map;
find_and_execute(some_map, 1,
[](int key, int value){ std::cout << "key " << key << " found, value: " << value << std::endl; },
[](int key){ std::cout << "key " << key << " not found" << std::endl; });
Недостатком этого является хорошее имя, "find_and_execute" неудобно, и я не могу придумать ничего лучше с моей головы...
C++17
немного упростил это с помощью If statement with initializer
.
Таким образом, вы можете съесть свой торт и съесть его тоже.
if ( auto it{ m.find( "key" ) }; it != std::end( m ) )
{
// Destructure the returned pair in to
// its sub components. Get them by reference.
// You can also get them by value.
auto&[ key, value ] { *it };
// Grab either the key or value stored in the pair.
// The key is stored in the 'first' variable and
// the 'value' is stored in the second.
auto& mkey{ it->first };
auto& mvalue{ it->second };
// That or just grab the entire pair pointed
// to by the iterator.
auto& pair{ *it };
}
else
{
// Key was not found..
}
Будьте внимательны при сравнении результата поиска с концом, как и для map 'm', поскольку все ответы имеют сделано выше map:: iterator я = m.find( "f" );
if (i == m.end())
{
}
else
{
}
вам не следует пытаться выполнять какую-либо операцию, такую как печать ключа или значения с помощью итератора i, если его значение равно m.end(), иначе это приведет к ошибке сегментации.
Сравнивая код std:: map:: find и std:: map:: count, я бы сказал, что первое может принести некоторое преимущество в производительности:
const_iterator find(const key_type& _Keyval) const
{ // find an element in nonmutable sequence that matches _Keyval
const_iterator _Where = lower_bound(_Keyval); // Here one looks only for lower bound
return (_Where == end()
|| _DEBUG_LT_PRED(this->_Getcomp(),
_Keyval, this->_Key(_Where._Mynode()))
? end() : _Where);
}
size_type count(const key_type& _Keyval) const
{ // count all elements that match _Keyval
_Paircc _Ans = equal_range(_Keyval); // Here both lower and upper bounds are to be found, which is presumably slower.
size_type _Num = 0;
_Distance(_Ans.first, _Ans.second, _Num);
return (_Num);
}
Я знаю, что на этот вопрос уже есть несколько хороших ответов, но я думаю, что мое решение стоит поделиться.
Он работает как для std::map
, так и для std::vector<std::pair<T, U>>
и доступен на С++ 11.
template <typename ForwardIterator, typename Key>
bool contains_key(ForwardIterator first, ForwardIterator last, Key const key) {
using ValueType = typename std::iterator_traits<ForwardIterator>::value_type;
auto search_result = std::find_if(
first, last,
[&key](ValueType const& item) {
return item.first == key;
}
);
if (search_result == last) {
return false;
} else {
return true;
}
}
Если вы хотите сравнить пару карт, вы можете использовать этот метод:
typedef map<double, double> TestMap;
TestMap testMap;
pair<map<double,double>::iterator,bool> controlMapValues;
controlMapValues= testMap.insert(std::pair<double,double>(x,y));
if (controlMapValues.second == false )
{
TestMap::iterator it;
it = testMap.find(x);
if (it->second == y)
{
cout<<"Given value is already exist in Map"<<endl;
}
}
Это полезный метод.
map <int , char>::iterator itr;
for(itr = MyMap.begin() ; itr!= MyMap.end() ; itr++)
{
if (itr->second == 'c')
{
cout<<itr->first<<endl;
}
}