1

我有一个map<int, map<int, int>>.

第一个键代表节点,第二个键代表一个属性,“最深”元素代表一个特定的值。

我需要检查该元素,但执行以下不必要的操作会向我的地图添加键:

map<int, map<int, int>> test;
if (test[4][3] > 5)
{
    //do something
}

我认为的替代方案是

map<int, map<int, int>> test;
if (test.find(4) != test.end())
{
    if (test[4].find(3) != test[4].end())
    {
        if (test[4][3] > 5)
        {
            //do something
        }
    }
}

有一个更好的方法吗?我不知道地图中是否存在密钥[4][3],我不想不必要地添加它。谢谢!

4

3 回答 3

3

这应该有效 - 首先您在第一个地图中搜索并保存返回的迭代器,然后如果该迭代器有效,则搜索他指向的地图并将结果保存在另一个迭代器中,如果他有效,则意味着您寻找的对象存在,您只需检查它的值:

map<int, map<int, int>> test;
map<int, map<int, int>>::iterator it1;
map<int, int>::iterator it2;
if ((it1 = test.find(4)) != test.end())
{
    if ((it2 = it1->second.find(3)) != it1->second.end())
    {
        if (it2->second > 5)
        {
            //do something
        }
    }
}
return 0;
于 2013-06-20T08:17:26.323 回答
1

与 Tomer Arazy 的建议没有根本不同,但使用 C++11decltype来摆脱重复的类型声明(更正这在修改映射的数据类型时可能很乏味):

#include <map>
#include <iostream>

int main()
{
  using std::map;

  map<int, map<int, int>> test;
  test[4][3] = 6;

  decltype(test.begin())                 outer;
  decltype(test.begin()->second.begin()) inner;

  if (((outer = test.find(4)) != test.end())
      && ((inner = outer->second.find(3)) != outer->second.end())
      && (inner->second > 5))
    std::cout << "Found!" << std::endl;

  return 0;
}

(请注意,参数 ofdecltype()没有被评估,所以即使地图是空的,这也有效。)

这显然只适用于 C++11。


在 C++11 的上下文中要提到的另一件事是,std::map它现在具有at()类似于std::vector. 它返回给定键的值,如果键不存在则抛出异常。如果您将不存在密钥视为错误条件,这只是一个有用的想法。但如果是这样,你可以使用

if (test.at(4).at(3) > 5)
  std::cout << "Found!" << std::endl;

然后可能在某处捕获std::out_of_range异常。

于 2013-06-20T08:53:23.940 回答
0

我认为这可能会让你更容易看到发生了什么:

map<int, map<int, int>> test; 
map<int, map<int, int>>::iterator outer = test.find(4);
if (outer != test.end())
{
    map<int, int>::iterator inner = outer->second.find(3);
    if (inner != outer->second.end())
    {
        if (inner->second > 5)
        {
            //do something
        }
    }
}
return 0;
于 2013-06-20T08:28:37.187 回答