ChatGPT解决这个技术问题 Extra ChatGPT

确定地图是否包含键的值?

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

这些方面的东西是否存在?


v
vPraetor

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

if (m.count(key))
    // key exists

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


即使它已经找到一个,这不会检查所有的键吗?那可能很快就会变得昂贵......
如果在多图上使用,它只会计算一个以上的键。
@mmdanziger 不,它不会很贵:cplusplus.com/reference/map/map/count 计数是对数大小。
密钥存在,然后呢?那时,您通常希望获得它的价值,并为另一次搜索付费(例如使用 operator[])。 find 为您提供 .NET 的 TryGetValue 语义,这几乎总是您(尤其是 OP)想要的。
@serine 明白了。请注意,如果发布时缺少键,则行为会有所不同,因为 map[key] 将返回一个新的默认构造的元素值。
A
Alan

这些方面的东西是否存在?

不。使用 stl 地图类,您使用 ::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);


怎么会这样? findcount 更好地表明意图。此外,count 不返回该项目。如果您阅读 OP 的问题,他想检查是否存在, 返回元素。 find 这样做。 count 没有。
我一直很好奇设计整个 stl API 的人在吸食什么样的杂草。
Alan 我必须同意@dynamic 关于这一点,必须定义一个迭代器然后将其与 end 进行比较并不是说某事不存在的自然方式。对我来说,说某个元素在这张地图中至少出现一次似乎要简单得多。这就是 count 的作用。
@Claudiu C++20 补充了这一点。
只有 C++ 程序员会回答“否”,然后完美地回答这个问题。
k
kebs

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

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

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


最后一个关于这个功能的答案! (C++20)
最后 ?谢谢,但它已经快 2 岁了! ;-)
希望人们将滚动到此解决方案,并且不再使用已弃用的解决方案。 :)
他们只花了到 2020 年,也许到 2050 年他们会有模块。
cppreference 在这个函数旁边说“(C++20)”时,我确信我错过了一些东西……说真的,这是一个如此明显的函数;我很震惊他们花了这么长时间。
s
stinky472

它已经存在于 find only 而不是那种确切的语法。

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

A
Alex Martelli

amap.find 找不到您要查找的内容时,它会返回 amap::end——您应该检查一下。


c
cdahms

简明扼要地总结其他一些答案:

如果您还没有使用 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
}

B
Berk Soysal

对照 end 检查 find 的返回值。

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

n
netjeff

您可以使用以下代码创建 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;
}

我相信第 6 行应该是 out = foundIter->second
我修复了 Kip 的答案以正确显示 out = foundIter->second 而不是 out = *foundIter
S
Safin Ghoghabori

Map 提供了 2 个成员函数来检查给定的键是否存在于具有不同返回值的映射中,即

std::map::find (返回迭代器) std::map::count (返回计数)

使用 std::map::count 检查 map 是否包含键

它使用键 K 查找并返回映射中元素的数量。因为映射仅包含具有唯一键的元素。因此,如果 key 存在则返回 1,否则返回 0。

使用 std::map::find 检查 map 是否包含键

它检查映射中是否存在具有给定键“k”的任何元素,如果存在则返回其迭代器,否则返回映射的结尾。

有关更多详细信息和示例,请参阅以下链接(易于理解的说明)。

学分:https://thispointer.com/how-check-if-a-given-key-exists-in-a-map-c/


P
Prashant Shubham

如果要判断某个键是否存在于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;
}

S
Shail Gautam

Boost multiindex可用于适当的解决方案。以下解决方案不是最好的选择,但在用户在初始化时分配默认值(如 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;
}