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?
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;
}
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
}
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_map
s anzuwenden
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]
}
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