检查 unordered_map of unordered_map 是否包含密钥的最简单方法
Simplest method to check whether unordered_map of unordered_maps contains key
我正在使用 unordered_map 的 unordered_map,这样我就可以使用 "multi key" 语法引用元素:
my_map[k1][k2]
。
有没有一种方便的方法可以使用相同的 "multi-key" 语法在尝试访问某个元素之前检查该元素是否存在?如果没有,最简单的方法是什么?
如果你的目的是测试密钥是否存在,我不会使用
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
}
如果你想创建一个函数来检查两个键是否存在,那么你可以写类似
的东西
//------------------------------------------------------------------------------
/// \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;
}
我认为没有 multi-key 语法可以检查,但最简单的方法是使用 find
方法。您可以编写一个简单的函数将其应用于 unordered_map
of unordered_map
s
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...);
}
将适用于每个 single-valued 关联容器。
如果存在包含 k2
. 的元素 k1
,则 contains(my_map, k1, k2)
为真
是这样的吗? (对于可变案例)
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-like 方法...
try {
auto& v = my_map.at(k1).at(k2);
// use v
}
catch(const std::out_of_range & e) {
// didn't find it
}
您也可以使用计数 (http://www.cplusplus.com/reference/unordered_map/unordered_map/count/ )
如果键不存在,return 0
在C++20中,可以使用contains
方法(如果我没记错的话添加到所有关联容器):
if (my_map.contains(k1) && my_map[k1].contains(k2))
{
// do something with my_map[k1][k2]
}
另一种方法是使用std::pair
作为键,将二级散列table转换为一级散列table,好处:
- 更简单的代码和结构
- 可能比两级散列更快table(我们调用更少的散列函数,获得更紧凑的内存布局以便对缓存更友好)
缺点:我们有一些键冗余,所以对于有很多重复的大键来说,这将是一个糟糕的选择,但这种情况不会太常见,所以这里的策略仍然有用。
std::unordered_map<std::pair<int, int>, int> map;
然后检查是否存在:
使用结束迭代器进行查找和比较
map.find(std::make_pair(k0, k1)) != map.end()
带计数功能(注意不要和unordered_multimap一起使用)
map.count(std::make_pair(k0, k1)) != 0
或 C++20 包含:
map.contains(std::make_pair(k0, k1))
我正在使用 unordered_map 的 unordered_map,这样我就可以使用 "multi key" 语法引用元素:
my_map[k1][k2]
。
有没有一种方便的方法可以使用相同的 "multi-key" 语法在尝试访问某个元素之前检查该元素是否存在?如果没有,最简单的方法是什么?
如果你的目的是测试密钥是否存在,我不会使用
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
}
如果你想创建一个函数来检查两个键是否存在,那么你可以写类似
的东西//------------------------------------------------------------------------------
/// \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;
}
我认为没有 multi-key 语法可以检查,但最简单的方法是使用 find
方法。您可以编写一个简单的函数将其应用于 unordered_map
of unordered_map
s
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...);
}
将适用于每个 single-valued 关联容器。
如果存在包含k2
. 的元素 k1
,则 contains(my_map, k1, k2)
为真
是这样的吗? (对于可变案例)
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-like 方法...
try {
auto& v = my_map.at(k1).at(k2);
// use v
}
catch(const std::out_of_range & e) {
// didn't find it
}
您也可以使用计数 (http://www.cplusplus.com/reference/unordered_map/unordered_map/count/ )
如果键不存在,return 0
在C++20中,可以使用contains
方法(如果我没记错的话添加到所有关联容器):
if (my_map.contains(k1) && my_map[k1].contains(k2))
{
// do something with my_map[k1][k2]
}
另一种方法是使用std::pair
作为键,将二级散列table转换为一级散列table,好处:
- 更简单的代码和结构
- 可能比两级散列更快table(我们调用更少的散列函数,获得更紧凑的内存布局以便对缓存更友好)
缺点:我们有一些键冗余,所以对于有很多重复的大键来说,这将是一个糟糕的选择,但这种情况不会太常见,所以这里的策略仍然有用。
std::unordered_map<std::pair<int, int>, int> map;
然后检查是否存在:
使用结束迭代器进行查找和比较
map.find(std::make_pair(k0, k1)) != map.end()
带计数功能(注意不要和unordered_multimap一起使用)
map.count(std::make_pair(k0, k1)) != 0
或 C++20 包含:
map.contains(std::make_pair(k0, k1))