确定map是否包含键的值?

Nic*_*ner 228 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;

}
Run Code Online (Sandbox Code Playgroud)

在调试器中检查它,它看起来就像iter垃圾数据.

如果我取消注释这一行:

Bar b2 = m[2]
Run Code Online (Sandbox Code Playgroud)

调试器显示的b2{i = 0}.(我猜这意味着使用未定义的索引会返回一个包含所有空/未初始化值的结构?)

这些方法都不是很好.我真正喜欢的是这样的界面:

bool getValue(int key, Bar& out)
{
    if (map contains value for key)
    {
        out = map[key];
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

沿着这些线存在什么?

小智 305

只要地图不是多图,最优雅的方法之一就是使用count方法

if (m.count(key))
    // key exists
Run Code Online (Sandbox Code Playgroud)

如果元素确实存在于地图中,则计数将为1.

  • 如果在多图上使用它,它将只计算多个键. (32认同)
  • 关键存在,然后是什么?那时你通常想要获得它的价值,支付另一个搜索(例如使用`operator []`).`find`为你提供.NET的`TryGetValue`语义,这几乎总是你(特别是OP)想要的. (26认同)
  • 即使它已经找到了,也不会检查*所有*键吗?这可能会变得昂贵快...... (21认同)
  • @mmdanziger不,它不会很贵:http://www.cplusplus.com/reference/map/map/count/ Count的大小是对数的. (14认同)
  • @serine了解。请注意,如果发布中缺少键,则行为会有所不同,因为map [key]将返回新的默认构造的元素值。 (2认同)

Ala*_*lan 253

沿着这些线存在什么?

不可以.使用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;
}
Run Code Online (Sandbox Code Playgroud)

显然你可以getValue()根据自己的需要编写自己的例程(也是在C++中,没有理由使用out),但是我怀疑一旦你掌握了使用它就std::map::find()不会浪费你的时间.

你的代码也有点错误:

m.find('2');将在地图中搜索关键值'2'.IIRC C++编译器将隐式地将'2'转换为int,这导致'2'的ASCII代码的数值,这不是你想要的.

由于您在此示例中的键类型是int要搜索,如下所示:m.find(2);

  • 我一直很好奇是什么样的杂草吸食了设计整个API的人. (45认同)
  • 是的,很好地抓住了''2'`v.`2`错误. (9认同)
  • 怎么会这样?`find`表示意图比`count`好得多.更重要的是,`count`不会返回该项目.如果您阅读OP的问题,他想检查是否存在,*和*返回元素.`find`做到了.`count`没有. (7认同)
  • 这个答案听起来好多了:http://stackoverflow.com/a/11765524/496223 (4认同)
  • 只有c++程序员才会回答“否”,然后完美地回答这个问题。 (3认同)
  • 迂腐是 C++ 编程的首要原则 (3认同)
  • Alan我必须同意@dynamic这个,必须定义一个迭代器然后将它与end进行比较并不是说不存在某种东西的自然方式.对于我来说,在这张地图中至少出现一次某个元素似乎更直截了当.算是做什么的. (2认同)
  • @Cludiu C++20 补充了这一点。 (2认同)

sti*_*472 50

它已经存在,只有查找不是那种确切的语法.

if (m.find(2) == m.end() )
{
    // key 2 doesn't exist
}
Run Code Online (Sandbox Code Playgroud)

如果要访问该值(如果存在),您可以执行以下操作:

map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}
Run Code Online (Sandbox Code Playgroud)

使用C++ 0x和auto,语法更简单:

auto iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}
Run Code Online (Sandbox Code Playgroud)

我建议你习惯它,而不是试图想出一个新的机制来简化它.您可以减少一些代码,但要考虑这样做的成本.现在,您已经介绍了一个熟悉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;
}
Run Code Online (Sandbox Code Playgroud)


keb*_*ebs 24

我只是注意到使用C++ 20,我们会有

bool std::map::contains( const Key& key ) const;
Run Code Online (Sandbox Code Playgroud)

如果map持有带键的元素,那将返回true key.

  • 终于有一个关于这个功能的答案了!(C++20) (7认同)
  • 希望人们能够滚动到这个解决方案,并且不再使用已弃用的解决方案。:) (6认同)
  • 他们只花了 2020 年,也许到 2050 年他们就会拥有模块。 (3认同)

cda*_*hms 9

简单总结一下其他一些答案:

如果您还没有使用 C++ 20,您可以编写自己的mapContainsKey函数:

bool mapContainsKey(std::map<int, int>& map, int key)
{
  if (map.find(key) == map.end()) return false;
  return true;
}
Run Code Online (Sandbox Code Playgroud)

如果您想避免mapvsunordered_map以及不同的键和值类型的许多重载,您可以将其设为template函数。

如果你正在使用C++ 20或以后,会有一个内置contains函数:

std::map<int, int> myMap;

// do stuff with myMap here

int key = 123;

if (myMap.contains(key))
{
  // stuff here
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 7

amap.findamap::end当它找不到你想要的东西时返回- 你应该检查它.


Jar*_*Par 6

find检查against的返回值end

map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) { 
  // contains
  ...
}
Run Code Online (Sandbox Code Playgroud)