Самый простой способ проверить, содержит ли неупорядоченная карта неупорядоченных карт ключ
Я использую unordered_map из unordered_map, так что я могу ссылаться на элемент, используя синтаксис "multi key":
my_map[k1][k2]
.
Есть ли удобный способ использовать тот же синтаксис "мульти-ключа", чтобы проверить, существует ли элемент, прежде чем пытаться получить к нему доступ? Если нет, то какой самый простой способ?
5 ответов:
Если ваше намерение состоит в том, чтобы проверить наличие ключа, я бы не использовал
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; }
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...); }
Будет работать для каждого однозначного ассоциативного контейнера.
contains(my_map, k1, k2)
истинно, если существует элемент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 }
... или есть более питоноподобный способ...
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
Вы также можете использовать count (http://www.cplusplus.com/reference/unordered_map/unordered_map/count/ )
Который вернет 0, если ключ не существует