如何找到一个给定的关键是否存在于一个c++ std::映射

我试图检查一个给定的键是否在一个映射中,有点不能这样做:

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中的内容呢?

849816 次浏览

你可以使用.find():

map<string,string>::iterator i = m.find("f");


if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }

我觉得你想要map::find。如果m.find("f")等于m.end(),则没有找到密钥。否则,find返回指向所找到元素的迭代器。

这个错误是因为p.first是一个迭代器,它不适用于流插入。将最后一行更改为cout << (p.first)->first;p是一对迭代器,p.first是一个迭代器,p.first->first是键字符串。

对于一个给定的键,映射只能有一个元素,所以equal_range不是很有用。它是为map定义的,因为它是为所有关联容器定义的,但它对multimap更有趣。

使用map::findmap::end:

if (m.find("f") == m.end()) {
// not found
} else {
// found
}
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";
在将find结果与map 'm'的结束进行比较时要小心,因为所有的答案都有 完成以上 Map::iterator I = m.find("f");

 if (i == m.end())
{
}
else
{
}

如果迭代器I等于m.end(),你不应该尝试执行任何操作,比如打印键或值,否则会导致分割错误。

要检查映射中是否存在特定的键,可以通过以下方式之一使用count成员函数:

m.count(key) > 0
m.count(key) == 1
m.count(key) != 0

map::find文档表示:“另一个成员函数map::count可用于检查特定键是否存在。”

map::count文档表示:“因为映射容器中的所有元素都是唯一的,所以函数只能返回1(如果找到元素)或0(否则)。”

通过一个你知道存在的键从映射中检索一个值,使用地图:::

value = m.at(key)

地图:运营商[]不同,如果指定的键不存在,map::at将不会在映射中创建新键。

map<string, string> m;

检查键是否存在,并返回发生的个数(map中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.firstmap<string, string>,你不能打印出来。试试这个:

if(p.first != p.second) {
cout << p.first->first << " " << p.first->second << endl;
}

比较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);
}

如果你想比较一对地图,你可以使用这个方法:

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;
}
}

这是一个有用的技巧。

template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
return (container.find(key) != std::end(container));
}

当然,如果你想要更花哨一点,你总是可以模板化一个函数,同时取一个已找到的函数和一个未找到的函数,就像这样:

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”是尴尬的,我不能想出任何更好的在我的头顶…

map <int , char>::iterator itr;
for(itr = MyMap.begin() ; itr!= MyMap.end() ; itr++)
{
if (itr->second == 'c')
{
cout<<itr->first<<endl;
}
}

C + + 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";
}
}

C++17If statement with initializer简化了一点。 这样你就可以鱼与熊掌兼得了

if ( auto it{ m.find( "key" ) }; it != std::end( m ) )
{
// Use `structured binding` to get the key
// and value.
const 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.
const auto& mkey{ it->first };
const auto& mvalue{ it->second };


// That or just grab the entire pair pointed
// to by the iterator.
const auto& pair{ *it };
}
else
{
// Key was not found..
}

我知道这个问题已经有了一些很好的答案,但我认为我的解决方案值得分享。

它适用于std::mapstd::vector<std::pair<T, U>>,并且可以从c++ 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;
}
}