Jak sprawdzić, czy std :: map zawiera klucz bez wykonywania wstawiania?

148

Jedynym sposobem znalazłem sprawdzić duplikatów jest przez włożenie i sprawdzenie std::pair.secondza false, ale problemem jest to, że nadal wstawia coś, jeśli klucz jest nieużywany, natomiast to, co chcę jest map.contains(key);funkcja.

jmasterx
źródło

Odpowiedzi:

305

Użyj my_map.count( key ); może zwrócić tylko 0 lub 1, co jest w istocie wynikiem logicznym, którego chcesz.

Alternatywnie my_map.find( key ) != my_map.end()działa też.

Potatoswatter
źródło
40
@John: To cuchnie przedwczesną optymalizacją. Na GCC (i jestem pewien, że większość rozsądnych systemów) map::countjest zaimplementowany jako find(__x) == end() ? 0 : 1;. Na multimapmajowym masz argumentu wydajności, ale to nie jest kwestia OP i nadal preferują elegancję.
Potatoswatter
42
Nie, argument przedwczesnej optymalizacji jest ważny tylko wtedy, gdy optymalizacja wymaga pewnego wysiłku, co w tym przypadku nie.
markh44
13
Nie prawda. Nie jest to przedwczesne, jeśli ułatwia to odczytanie kodu lub eliminuje niepotrzebne obciążenie. W tym przypadku, jeśli count () i tak jest zaimplementowana przez find (), to wywołanie find () bezpośrednio eliminuje wywołanie funkcji ... ergo, to dojrzała optymalizacja. Uważam, że użycie wywołania find () jest również bardziej oczywiste, ale to czysto osobiste preferencje.
Tim Keating,
9
Nie jest przedwczesną optymalizacją, aby zdać sobie sprawę z perfekcji funkcji bibliotecznych, zanim nabędziesz nawyku ich używania. W tym przypadku masz rację, to nie ma znaczenia, ale nie ma też najmniejszej różnicy stylistycznej między znalezieniem a policzeniem. Myślę, że zbyt daleko posuwasz się z retoryką „przedwczesnej optymalizacji”. Powinieneś wziąć wszystkie „bezpłatne” nawyki optymalizacyjne, które możesz znaleźć i wykorzystać je w codziennym rozwoju. To właśnie wtedy, gdy programiści wpadają w pułapkę płacenia kosztów za czytelność / czas programowania / itp., Wszystko dla niezmierzonych „zysków wydajności”, przedwczesna retoryka optymalizacyjna staje się właściwą radą.
VoidStar
10
Tak daleko, std powinno po prostu dodać cholerną has(k)/ contains(k)jak każdą inną rozsądną klasę mapy na planecie. Słaby projekt interfejsu. Podejście find () jest zbyt rozwlekłe, a count(k)podejście zdecydowanie nie ma równości semantycznej z has(k). W tym przypadku też nie jest find(k). Sprawdź liczbę wyświetleń tego pytania.
Jarrod Smith
46

Odpowiedź Potatoswatter jest w porządku, ale wolę użyć findlub lower_boundzamiast tego. lower_boundjest szczególnie przydatne, ponieważ zwrócony iterator może być później użyty do wstawienia z podpowiedzią, jeśli chcesz wstawić coś z tym samym kluczem.

map<K, V>::iterator iter(my_map.lower_bound(key));
if (iter == my_map.end() || key < iter->first) {    // not found
    // ...
    my_map.insert(iter, make_pair(key, value));     // hinted insertion
} else {
    // ... use iter->second here
}
Chris Jester-Young
źródło
Różni się to nieco od tego, jak mówi, że to robi… jedyna różnica polega na tym, że obliczenie valuemoże zostać pominięte, jeśli wstawianie jest niepotrzebne.
Potatoswatter
1
Jasne, rozumiem, że OP nie dba o wstawianie, więc lower_boundrozwiązanie oparte na a jest przesadą. W pewnym sensie właśnie wspomniałem o mojej odpowiedzi „dla kompletności”; jak powiedziałem, twój jest całkowicie wystarczający. :-)
Chris Jester-Young
4
Tak, to dobra odpowiedź iz niczym się nie zgadzam. Wystarczy wskazać związek z alternatywą inserta priori. W rzeczywistości istnieje inna różnica, jeśli używasz a multimap, lower_boundmetoda wstawia na początku równoważnego zakresu, podczas gdy zwykła insertmetoda dodaje do końca zakresu.
Potatoswatter
2
Nie odpowiedź na pytanie, ale moje kiepskie pytanie prowadzi mnie do właściwej odpowiedzi tutaj ... Muszę zrobić wstawienie / aktualizację. : D
Hunter-Orionnoir
1
@Hunter Czy możesz pokazać mi swój kod? Jeśli nie jest masywny, prawdopodobnie mogę go dla Ciebie przejrzeć.
Chris Jester-Young
8

Twoje dezyderatum,, map.contains(key)jest zaplanowane na projekt standardu C ++ 2a . W 2017 roku został zaimplementowany przez gcc 9.2 . Jest również w obecnym brzęku .

Camille Goudeseune
źródło
To fajna funkcja! Myślę, że wylądował na C ++ 20. cppreference.com
Franklin Yu