确定STL地图是否包含给定密钥的值的最佳方法是什么?
#include <map>
using namespace std;
struct Bar
{
int i;
};
int main()
{
map<int, Bar> m;
Bar b = {0};
Bar b1 = {1};
m[0] = b;
m[1] = b1;
//Bar b2 = m[2];
map<int, Bar>::iterator iter = m.find(2);
Bar b3 = iter->second;
}
在调试器中检查这一点,看起来iter
只是垃圾数据。
如果我取消注释这一行:
Bar b2 = m[2]
调试器显示b2
为{i = 0}
。 (我猜这意味着使用未定义的索引将返回一个包含所有空/未初始化值的结构?)
这两种方法都不是很好。我真正喜欢的是这样的界面:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
是否存在这些方面的内容?
答案 0 :(得分:286)
只要地图不是多图,最优雅的方法之一就是使用count方法
if (m.count(key))
// key exists
如果元素确实存在于地图中,则计数为1。
答案 1 :(得分:230)
是否存在这些方面的内容?
没有。使用stl map类,使用::find()
搜索地图,并将返回的迭代器与std::map::end()
进行比较
所以
map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}
显然你可以根据需要编写自己的getValue()
例程(也在C ++中,没有理由使用out
),但是我会怀疑,一旦你掌握了std::map::find()
你不会浪费你的时间。
您的代码也有些错误:
m.find('2');
会在地图中搜索'2'
的关键值。 IIRC C ++编译器将隐式地将'2'转换为int,这导致'2'的ASCII代码的数值,这不是你想要的。
由于此示例中的密钥类型为int
,您希望按以下方式进行搜索: m.find(2);
答案 2 :(得分:49)
它已经存在,只有查找不是那种确切的语法。
if (m.find(2) == m.end() )
{
// key 2 doesn't exist
}
如果要访问该值(如果存在),您可以执行以下操作:
map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
使用C ++ 0x和auto,语法更简单:
auto iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
我建议你习惯它,而不是试图想出一个新的机制来简化它。您可以减少一些代码,但要考虑这样做的成本。现在你已经介绍了一个熟悉C ++的人无法识别的新功能。
如果你想要实现这一点,尽管有这些警告,那么:
template <class Key, class Value, class Comparator, class Alloc>
bool getValue(const std::map<Key, Value, Comparator, Alloc>& my_map, int key, Value& out)
{
typename std::map<Key, Value, Comparator, Alloc>::const_iterator it = my_map.find(key);
if (it != my_map.end() )
{
out = it->second;
return true;
}
return false;
}
答案 3 :(得分:17)
答案 4 :(得分:7)
amap.find
在找不到您要找的内容时会返回amap::end
- 您应该检查该内容。
答案 5 :(得分:4)
检查find
对end
的返回值。
map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) {
// contains
...
}
答案 6 :(得分:1)
您可以使用以下代码创建getValue函数:
bool getValue(const std::map<int, Bar>& input, int key, Bar& out)
{
std::map<int, Bar>::iterator foundIter = input.find(key);
if (foundIter != input.end())
{
out = foundIter->second;
return true;
}
return false;
}
答案 7 :(得分:0)
如果要确定某个键是否存在于map中,可以使用map的find()或count()成员函数。 这里使用的find函数返回迭代器到element或map :: end。 在计数的情况下,如果找到则计数返回1,否则返回零(或其他)。
if(phone.count(key))
{ //key found
}
else
{//key not found
}
for(int i=0;i<v.size();i++){
phoneMap::iterator itr=phone.find(v[i]);//I have used a vector in this example to check through map you cal receive a value using at() e.g: map.at(key);
if(itr!=phone.end())
cout<<v[i]<<"="<<itr->second<<endl;
else
cout<<"Not found"<<endl;
}
答案 8 :(得分:0)
简要总结一些其他答案:
如果您还没有使用C ++ 20,则可以编写自己的mapContainsKey
函数:
bool mapContainsKey(std::map<int, int> map, int key)
{
if (map.find(key) == map.end()) return false;
return true;
}
如果您想避免map
与unordered_map
的重载以及不同的键和值类型,可以将其设为template
函数。
如果您使用的是C++ 20
或更高版本,将有一个内置的contains
函数:
std::map<int, int> myMap;
// do stuff with myMap here
int key = 123;
if (myMap.contains(key))
{
// stuff here
}
答案 9 :(得分:-1)
Boost multindex可用于正确解决方案。 以下解决方案不是一个非常好的选项,但在用户在初始化时分配默认值(如0或NULL)以及想要检查值是否已被修改的少数情况下可能很有用。
Ex.
< int , string >
< string , int >
< string , string >
consider < string , string >
mymap["1st"]="first";
mymap["second"]="";
for (std::map<string,string>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
if ( it->second =="" )
continue;
}