Jaki jest najlepszy sposób ustalenia, czy mapa STL zawiera wartość dla danego klucza?
#include <map>
using namespace std;
struct Bar
{
int i;
};
int main()
{
map<int, Bar> m;
Bar b = {0};
Bar b1 = {1};
m[0] = b;
m[1] = b1;
//Bar b2 = m[2];
map<int, Bar>::iterator iter = m.find(2);
Bar b3 = iter->second;
}
Analizując to w debugerze, wygląda na to, że iter
to tylko śmieciowe dane.
Jeśli odkomentuję tę linię:
Bar b2 = m[2]
Debuger pokazuje, że tak b2
jest {i = 0}
. (Zgaduję, że oznacza to, że użycie niezdefiniowanego indeksu zwróci strukturę ze wszystkimi pustymi / niezainicjowanymi wartościami?)
Żadna z tych metod nie jest tak świetna. Naprawdę chciałbym taki interfejs:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
Czy istnieje coś podobnego?
Odpowiedzi:
Nie. Za pomocą klasy mapy stl możesz
::find()
przeszukiwać mapę i porównywać z nią zwrócony iteratorstd::map::end()
więc
Oczywiście możesz napisać własną
getValue()
procedurę, jeśli chcesz (także w C ++, nie ma powodu, aby używaćout
), ale podejrzewam, że kiedy już zaczniesz używaćstd::map::find()
, nie będziesz chciał tracić czasu.Również twój kod jest nieco niepoprawny:
m.find('2');
przeszuka mapę w poszukiwaniu wartości klucza, która jest'2'
. IIRC kompilator C ++ niejawnie konwertuje „2” na int, co skutkuje wartością liczbową kodu ASCII dla „2”, co nie jest tym, czego chcesz.Ponieważ kluczem w tym przykładzie jest
int
wyszukiwanie w następujący sposób:m.find(2);
źródło
find
wskazuje na zamiar znacznie lepiej niżcount
robi. Co więcej,count
nie zwraca przedmiotu. Jeśli przeczytasz pytanie PO, chce sprawdzić, czy istnieje, i zwrócić element.find
robi to.count
nie.Tak długo, jak mapa nie jest mapą wielokrotną, jednym z najbardziej eleganckich sposobów byłoby użycie metody liczenia
Liczba będzie wynosić 1, jeśli element rzeczywiście jest obecny na mapie.
źródło
operator[]
).find
dajeTryGetValue
semantykę .NET , która prawie zawsze jest tym, czego chcesz (a konkretnie OP).Już istnieje, ale nie tylko w tej dokładnej składni.
Jeśli chcesz uzyskać dostęp do wartości, jeśli istnieje, możesz:
W C ++ 0x i auto składnia jest prostsza:
Radzę raczej przyzwyczaić się do tego, niż próbować wymyślić nowy mechanizm, aby go uprościć. Być może uda ci się trochę skrócić kod, ale weź pod uwagę koszty. Teraz wprowadziłeś nową funkcję, której osoby znające C ++ nie będą w stanie rozpoznać.
Jeśli mimo to chcesz je wdrożyć, mimo to:
źródło
Właśnie zauważyłem, że z C ++ 20 będziemy mieli
Zwróci to wartość true, jeśli mapa zawiera element z kluczem
key
.źródło
amap.find
zwraca,amap::end
gdy nie znajdzie tego, czego szukasz - musisz to sprawdzić.źródło
Sprawdź wartość zwracaną
find
Przeciwend
.źródło
Możesz utworzyć swoją funkcję getValue za pomocą następującego kodu:
źródło
out = foundIter->second
out = foundIter->second
zamiastout = *foundIter
Aby zwięźle streścić niektóre inne odpowiedzi:
Jeśli nie używasz jeszcze C ++ 20, możesz napisać własną
mapContainsKey
funkcję:Jeśli chcesz uniknąć wielu przeciążeń dla
map
vsunordered_map
i różnych typów kluczy i wartości, możesz włączyć tętemplate
funkcję.Jeśli używasz
C++ 20
lub później, będzie wbudowanacontains
funkcja:źródło
Jeśli chcesz ustalić, czy klucz znajduje się na mapie, możesz użyć funkcji członkowskiej find () lub count () mapy. Funkcja find, która jest użyta tutaj w tym przykładzie, zwraca iterator do elementu lub map :: end w przeciwnym razie. W przypadku liczenia liczba zwraca 1, jeśli zostanie znaleziona, w przeciwnym razie zwraca zero (lub w inny sposób).
źródło
Boind multindex może być użyty do właściwego rozwiązania. Poniższe rozwiązanie nie jest najlepszą opcją, ale może być przydatne w kilku przypadkach, w których użytkownik przy inicjalizacji przypisuje wartość domyślną, np. 0 lub NULL, i chce sprawdzić, czy wartość została zmodyfikowana.
źródło