web-dev-qa-db-fra.com

Méthode la plus simple pour vérifier si unordered_map of unordered_maps contient la clé

J'utilise un uneredered_map de unordered_maps, de sorte que je puisse référencer un élément en utilisant la syntaxe "multi key"

my_map[k1][k2]

Existe-t-il un moyen pratique d’utiliser la même syntaxe «multi-clé» pour vérifier l’existence d’un élément avant d’essayer d’y accéder? Si non, quel est le moyen le plus simple?

24
user997112

Si votre intention est de vérifier l’existence de la clé, je n’utiliserais pas

my_map[k1][k2]

parce que operator[] construira par défaut une nouvelle valeur pour cette clé si elle n'existe pas déjà.

Je préférerais plutôt utiliser std::unordered_map::find . Donc, si vous êtes certain que la première clé existe, mais pas la seconde, vous pouvez le faire.

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

Si vous souhaitez créer une fonction qui vérifie l'existence de touches deux, vous pouvez écrire quelque chose comme:

//------------------------------------------------------------------------------
/// \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;
}
30
CoryKramer
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...);
}

fonctionnera pour chaque conteneur associatif à valeur unique.

contains(my_map, k1, k2) est vrai s'il existe un élément k1 qui contient k2.

3

Quelque chose comme ça? (pour le cas mutable)

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 };
}

appelé comme si:

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
}

... ou il y a la manière plus python.

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

Je ne crois pas qu'il y ait une syntaxe multi-clé à vérifier, mais le moyen le plus simple serait d'utiliser la méthode find. Vous pourriez écrire une fonction simple pour l'appliquer à un unordered_map de unordered_maps

référence

0
Aiden Deom

Vous pouvez également utiliser count ( http://www.cplusplus.com/reference/unordered_map/unordered_map/count/ )

qui retournera 0 si la clé n'existe pas

0
Hui Liu