确定map是否包含键的值?

时间:2010-06-28 22:10:16

标签: c++ stl map

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

是否存在这些方面的内容?

10 个答案:

答案 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)

我刚刚注意到,有了C++20,我们将拥有

std::map::contains( const Key& key ) const;

如果map包含具有键key的元素,则返回true。

答案 4 :(得分:7)

amap.find在找不到您要找的内容时会返回amap::end - 您应该检查该内容。

答案 5 :(得分:4)

检查findend的返回值。

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

如果您想避免mapunordered_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;
}