c++ 检查unordered_maps的unordered_map是否包含键的最简单方法

mitkmikd  于 2023-03-14  发布在  其他
关注(0)|答案(7)|浏览(195)

我使用的是unordered_maps的unordered_map,这样我就可以使用“multi key”语法引用一个元素:
my_map[k1][k2] .
有没有一种方便的方法可以使用相同的“多键”语法在试图访问一个元素之前检查它是否存在?如果没有,最简单的方法是什么?

polkgigr

polkgigr1#

如果您的目的是测试密钥是否存在,我不会使用

my_map[k1][k2]

因为operator[]将默认地为该键构造一个新值(如果它还不存在的话)。
相反,我更愿意使用std::unordered_map::find。因此,如果您确定第一个键存在,但第二个键不存在,您可以这样做

if (my_map[k1].find(k2) != my_map[k1].end())
{
    // k2 exists in unordered_map for key k1
}

如果您想创建一个函数来检查both键是否存在,那么您可以编写如下代码

//------------------------------------------------------------------------------
/// \brief Determines a nested map contains two keys (the outer containing the inner)
/// \param[in] data Outer-most map
/// \param[in] a    Key used to find the inner map
/// \param[in] b    Key used to find the value within the inner map
/// \return True if both keys exist, false otherwise
//------------------------------------------------------------------------------
template <class key_t, class value_t>
bool nested_key_exists(std::unordered_map<key_t, std::unordered_map<key_t, value_t>> const& data, key_t const a, key_t const b)
{
    auto itInner = data.find(a);
    if (itInner != data.end())
    {
        return itInner->second.find(b) != itInner->second.end();
    }
    return false;
}
eni9jsuy

eni9jsuy2#

template<class M>
bool contains(M const&){return true;}
template<class M, class K, class...Ks>
bool contains(M const&m, K const&k, Ks const&...ks){
  auto it=m.find(k);
  if (it==m.end()) return false;
  return contains(it->second, ks...);
}

将适用于每个单值关联容器。
如果存在包含k2的元素k1,则contains(my_map, k1, k2)为真。

6g8kf2rb

6g8kf2rb3#

在C++20中,你可以使用contains方法(如果我没记错的话,添加到所有的关联容器中):

if (my_map.contains(k1) && my_map[k1].contains(k2))
{
    // do something with my_map[k1][k2]
}
dwthyt8l

dwthyt8l5#

像这样的东西吗?(对于可变的情况)

using inner_map = std::map<key_type, value_type>;
using outer_map = std::map<key_type, inner_map>

boost::optional<value_type&> 
element_for_keys(outer_map& map, const key_type& k1, const key_type& k2)
{
  auto it_outer = map.find(k1);
  if (it_outer = map.end())
    return {};
  auto &map2 = it_outer->second;
  auto it_inner = map2.find(k2);
  if (it_inner == map2.end())
    return {};

  return { it_inner->second };
}

名字是这样的:

auto op_value = element_for_keys(my_map, kv1, kv2);
if (op_value) {
  // use op_value.value()
}
else {
  // handle case where it does not exist
}

......或者还有更像Python的方法......

try {
  auto& v = my_map.at(k1).at(k2);
  // use v
}
catch(const std::out_of_range & e) {
  // didn't find it
}
z9gpfhce

z9gpfhce6#

我不认为有多键语法需要检查,但最简单的方法是使用find方法,您可以编写一个简单的函数将其应用于unordered_map s的unordered_map
reference

jljoyd4f

jljoyd4f7#

另一种方法是使用std::pair作为将两级哈希表转换为一级哈希表的键,其优点是:

  • 代码和结构更简单
  • 可能比两级哈希表更快(我们调用更少的哈希函数,获得更紧凑的内存布局以更好地缓存)

缺点:我们有一些密钥冗余,所以对于有很多重复的大密钥来说,这将是一个糟糕的选择,但是这种情况不会太常见,所以这里的策略仍然有用。

std::unordered_map<std::pair<int, int>, int> map;

然后检查是否存在:
使用查找和比较结束迭代器

map.find(std::make_pair(k0, k1)) != map.end()

使用count函数(注意不要将其与unordered_multimap一起使用)

map.count(std::make_pair(k0, k1)) != 0

或C++20包含:

map.contains(std::make_pair(k0, k1))

相关问题