Как проверить, содержит ли std :: map ключ без вставки?

148

Единственный способ, который я нашел для проверки на наличие дубликатов, - это вставка и проверка std::pair.secondfor false, но проблема в том, что он по-прежнему вставляет что-то, если ключ не используется, тогда как мне нужна map.contains(key);функция.

jmasterx
источник

Ответы:

305

Использование my_map.count( key ); он может возвращать только 0 или 1, что, по сути, является желаемым логическим результатом.

Поочередно my_map.find( key ) != my_map.end()работает тоже.

Potatoswatter
источник
40
@ Джон: Это пахнет преждевременной оптимизации. На GCC (и я уверен, что самые разумные системы), map::countреализован как find(__x) == end() ? 0 : 1;. Для multimapвас может быть аргумент производительности, но это не вопрос OP, и я все еще предпочитаю элегантность.
Potatoswatter
42
Нет, аргумент преждевременной оптимизации действителен только в том случае, если оптимизация требует определенных усилий, чего в этом случае нет.
markh44
13
Не правда. Это не преждевременно, если это облегчает чтение кода или устраняет ненужные накладные расходы. В этом случае, если count () так или иначе реализован через find (), то вызов find () напрямую устраняет вызов функции ... ergo, это зрелая оптимизация. Я считаю, что использование вызова find () также более очевидно, но это чисто личное предпочтение.
Тим Китинг
9
Это не преждевременная оптимизация - знать о функциях библиотеки, прежде чем вы привыкнете их использовать. В этом случае вы правы, это не имеет значения, но не имеет значения и незначительная стилистическая разница между поиском и подсчетом. Я думаю, вы слишком далеко зашли о риторике «преждевременной оптимизации». Вы должны использовать любые «бесплатные» привычки оптимизации, которые вы можете найти, и использовать их для повседневной разработки. Когда кодировщики преждевременной оптимизации становятся правильным советом, когда кодировщики поддаются ловушке оплаты затрат на удобочитаемость / время разработки / и т. Д., И все это за неизмеримое «повышение производительности».
VoidStar
10
Вне всяких сомнений, стандартному стандарту следует просто добавить чертовски has(k)/ contains(k)как и любой другой класс вменяемых карт на планете. Плохой дизайн интерфейса. Подход find () слишком многословен, и этот count(k)подход явно не соответствует семантическому равенству has(k). В этом отношении ни один не является find(k). Проверьте количество просмотров по этому вопросу.
Джаррод Смит
46

Potatoswatter ответ хорошо, но я предпочитаю использовать findили lower_boundвместо. lower_boundЭто особенно полезно, потому что возвращенный итератор может впоследствии использоваться для подсказки, если вы хотите вставить что-то с тем же ключом.

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
}
Крис Шут-Янг
источник
Это немного отличается от того, как он говорит, что делает это ... единственное отличие состоит в том, что вычисления valueмогут быть пропущены, если вставка не нужна.
Potatoswatter
1
Конечно, я понимаю, что OP не хочет вставлять, поэтому lower_boundрешение на основе является излишним. Я только что упомянул свой ответ "для полноты"; Как я уже сказал, ваш вполне адекватен. :-)
Крис Шестер-Янг
4
Да, это хороший ответ, и я ни с чем не согласен. Просто указывает на отношение к альтернативе insertаприори. На самом деле, есть еще одно различие , если с помощью multimap, то lower_boundметод вставки в начале эквивалентного диапазона , тогда как обычный insertметод добавляет к концу диапазона.
Potatoswatter
2
Не ответ на вопрос, но мой плохой вопрос приводит меня к правильному ответу здесь ... Мне нужно сделать вставку / обновление. : D
Охотник-Орионнуар
1
@Hunter Можете ли вы показать мне свой код? Если это не массивно, я, вероятно, могу рассмотреть это для вас.
Крис Шутер-Янг
9

Ваше пожелание map.contains(key)запланировано для проекта стандарта C ++ 2a . В 2017 году он был реализован GCC 9.2 . Это также в текущем лязге .

Камиль Гудесюн
источник
Это хорошая особенность! Я думаю, что он приземлился на C ++ 20. cppreference.com
Франклин Ю