web-dev-qa-db-de.com

Einfachste Methode zur Überprüfung, ob unordered_map von unordered_maps den Schlüssel enthält

Ich verwende eine unordered_map von unordered_maps, sodass ich ein Element mit der "multi key" -Syntax referenzieren kann:

my_map[k1][k2]

Gibt es eine bequeme Möglichkeit, dieselbe "Multi-Key" -Syntax zu verwenden, um zu prüfen, ob ein Element vorhanden ist, bevor versucht wird, darauf zuzugreifen? Wenn nicht, was ist der einfachste Weg?

24
user997112

Wenn Sie die Existenz des Schlüssels testen möchten, würde ich das nicht verwenden

my_map[k1][k2]

weil operator[] standardmäßig einen neuen Wert für diesen Schlüssel erstellt, falls er noch nicht vorhanden ist.

Ich würde lieber std::unordered_map::find verwenden. Wenn Sie sicher sind, dass der erste Schlüssel existiert, aber nicht der zweite, den Sie tun könnten

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

Wenn Sie eine Funktion erstellen möchten, die das Vorhandensein von beiden -Tasten überprüft, können Sie so etwas schreiben

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

funktioniert für jeden einwertigen assoziativen Container.

contains(my_map, k1, k2) ist wahr, wenn ein Element k1 vorhanden ist, das k2 enthält.

Etwas wie das? (für den veränderbaren Fall)

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

so genannt:

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
}

... oder es gibt den Python-ähnlichen Weg ...

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

Ich glaube nicht, dass es eine Multi-Key-Syntax gibt, die geprüft werden muss, aber die einfachste Möglichkeit wäre die Verwendung der find-Methode. Sie könnten eine einfache Funktion schreiben, um sie auf einen unordered_map von unordered_maps anzuwenden

Referenz

0
Aiden Deom

In C++ 20 können Sie die Methode contains verwenden (hinzugefügt zu allen assoziativen Containern, wenn ich mich nicht irre):

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

Sie können auch count verwenden ( http://www.cplusplus.com/reference/unordered_map/unordered_map/count/ )

welches wird 0 zurückgeben, wenn Schlüssel nicht vorhanden ist

0
Hui Liu