我正在使用一个无序映射的嵌套,以便我可以使用“多键”语法引用元素:
my_map[k1][k2]
。是否有一种便捷的方法来在尝试访问它之前检查元素是否存在呢?如果没有,最简单的方法是什么?my_map[k1][k2]
。是否有一种便捷的方法来在尝试访问它之前检查元素是否存在呢?如果没有,最简单的方法是什么?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;
}
k1
是否存在,您需要使用 find
两次 - 一次检查 k1
,另一次检查 k2
。 - zmbnested_key_exists
еҮҪж•°гҖӮеҰӮжһңдёӨдёӘй”®йғҪеӯҳеңЁпјҢеҲҷе®ғе°Ҷиҝ”еӣһtrue
пјҢеҗҰеҲҷиҝ”еӣһfalse
гҖӮ - Cory Kramermy_map[k1]
的值是否会被缓存,因此两次查找可能会很昂贵。 - Slavamy_map[k1]
检索到的内部映射可以存储在临时变量中,以避免两次查找。 - Cory Kramercontains
方法(如果我没记错的话,已添加到所有关联容器中):if (my_map.contains(k1) && my_map[k1].contains(k2))
{
// do something with my_map[k1][k2]
}
k1
搜索被执行了两次。更好的解决方案是,在单个k1
搜索的结果上执行k2
搜索。 - Remy Lebeautemplate<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...);
}
这将适用于每个单值关联容器。
contains(my_map, k1, k2)
如果存在一个元素k1
包含k2
,则返回 true。
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
}
我不相信有一个多键语法可以检查,但最简单的方法是使用find
方法。您可以编写一个简单的函数将其应用于unordered_map
的unordered_map
s。
另一种方法是使用std::pair
作为键,将两级哈希表转换为一级哈希表,其好处:
缺点:我们有一些键冗余,因此对于具有许多重复项的大键来说,这将是一个糟糕的选择,但这种情况不会太常见,因此这里的策略仍然很有用。
std::unordered_map<std::pair<int, int>, int> map;
然后检查是否存在:
使用find并与end迭代器进行比较
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))