Каков наилучший способ определить, содержит ли карта STL значение для данного ключа?
#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;
}
Рассматривая это в отладчике, похоже, что iter
это просто мусорные данные.
Если я раскомментирую эту строку:
Bar b2 = m[2]
Отладчик показывает что b2
есть {i = 0}
. (Я предполагаю, что это означает, что использование неопределенного индекса вернет структуру со всеми пустыми / неинициализированными значениями?)
Ни один из этих методов не так хорош. Что мне действительно нравится, так это интерфейс:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
Есть ли что-то подобное?
Ответы:
Нет. С помощью класса карты stl вы используете
::find()
поиск по карте и сравниваете возвращенный итератор сstd::map::end()
так
Очевидно, что вы можете написать свою собственную
getValue()
подпрограмму, если хотите (также в C ++ нет причин использоватьout
), но я подозреваю, что, как только вы освоите использование,std::map::find()
вы не захотите тратить свое время.Также ваш код немного неправильный:
m.find('2');
будет искать на карте ключевое значение, которое есть'2'
. IIRC компилятор C ++ неявно преобразует '2' в int, что приводит к числовому значению для кода ASCII для '2', а это не то, что вам нужно.Поскольку ваш тип ключа в этом примере,
int
вы хотите искать так:m.find(2);
источник
find
указывает на намерение гораздо лучше, чемcount
делает. Более того,count
не возвращает товар. Если вы прочитаете вопрос ОП, он захочет проверить наличие и вернуть элемент.find
делает этоcount
не.Пока карта не является мультикартой, одним из самых элегантных способов будет использование метода подсчета
Счет будет равен 1, если элемент действительно присутствует на карте.
источник
operator[]
).find
дает вамTryGetValue
семантику .NET , которая почти всегда то, что вы (и особенно ОП) хотите.Он уже существует с find только не в том же синтаксисе.
Если вы хотите получить доступ к значению, если оно существует, вы можете сделать:
С C ++ 0x и auto синтаксис проще:
Я рекомендую вам привыкнуть к этому, а не пытаться придумать новый механизм, чтобы упростить его. Возможно, вам удастся сократить объем кода, но подумайте о том, как это сделать. Теперь вы ввели новую функцию, которую люди, знакомые с C ++, не смогут распознать.
Если вы хотите реализовать это, несмотря на эти предупреждения, то:
источник
Я только что заметил, что с C ++ 20 у нас будет
Это вернет true, если карта содержит элемент с ключом
key
.источник
amap.find
возвращается,amap::end
когда не находит то, что вы ищете - вы должны это проверить.источник
Проверьте возвращаемое значение
find
противend
.источник
Вы можете создать свою функцию getValue с помощью следующего кода:
источник
out = foundIter->second
out = foundIter->second
а неout = *foundIter
Чтобы кратко суммировать некоторые из других ответов:
Если вы еще не используете C ++ 20, вы можете написать свою собственную
mapContainsKey
функцию:Если вы хотите избежать многих перегрузок для
map
vsunordered_map
и разных типов ключей и значений, вы можете сделать этоtemplate
функцией.Если вы используете
C++ 20
или позже, будет встроеннаяcontains
функция:источник
Если вы хотите определить, есть ли ключ на карте или нет, вы можете использовать функцию-член map (find) или count (). Функция find, которая используется здесь в примере, возвращает итератор element или map :: end в противном случае. В случае подсчета счетчик возвращает 1, если найден, иначе он возвращает ноль (или иначе).
источник
Boost multindex можно использовать для правильного решения. Следующее решение не очень лучший вариант, но может быть полезно в тех случаях, когда пользователь назначает значение по умолчанию, например 0 или NULL, при инициализации и хочет проверить, было ли изменено значение.
источник