Qual é a melhor maneira de determinar se um mapa STL contém um valor para uma determinada chave?
#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;
}
Examinando isso em um depurador, parece iter
apenas dados de lixo.
Se eu descomentar esta linha:
Bar b2 = m[2]
As mostras do depurador que b2
é {i = 0}
. (Acho que isso significa que o uso de um índice indefinido retornará uma estrutura com todos os valores vazios / não inicializados?)
Nenhum desses métodos é tão bom. O que eu realmente gostaria é de uma interface como esta:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
Existe algo nesse sentido?
Respostas:
Não. Com a classe stl map, você usa
::find()
para pesquisar o mapa e comparar o iterador retornado parastd::map::end()
tão
Obviamente, você pode escrever sua própria
getValue()
rotina, se quiser (também em C ++, não há motivo para usá-loout
), mas eu suspeitaria que, depois que você pegar o jeitostd::map::find()
, não vai querer perder tempo.Além disso, seu código está um pouco errado:
m.find('2');
procurará no mapa um valor-chave que seja'2'
. IIRC, o compilador C ++ converterá implicitamente '2' em um int, o que resulta no valor numérico do código ASCII para '2', que não é o que você deseja.Como seu tipo de chave neste exemplo é
int
você deseja pesquisar assim:m.find(2);
fonte
find
indica intenção muito melhor do quecount
faz. Mais,count
não retorna o item. Se você ler a pergunta do OP, ele deseja verificar a existência e retornar o elemento.find
faz isso.count
não.Desde que o mapa não seja multimap, uma das maneiras mais elegantes seria usar o método count
A contagem seria 1 se o elemento estiver realmente presente no mapa.
fonte
operator[]
).find
fornece aTryGetValue
semântica do .NET , que quase sempre é o que você (e especificamente o OP) deseja.Ele já existe com find e não apenas nessa sintaxe exata.
Se você deseja acessar o valor, se existir, você pode:
Com C ++ 0x e automático, a sintaxe é mais simples:
Eu recomendo que você se acostume a isso, em vez de tentar criar um novo mecanismo para simplificá-lo. Você pode reduzir um pouco de código, mas considere o custo de fazer isso. Agora você introduziu uma nova função que as pessoas familiarizadas com C ++ não poderão reconhecer.
Se você deseja implementar isso de qualquer maneira, apesar desses avisos, então:
fonte
Acabei de notar que, com o C ++ 20 , teremos
Isso retornará true se o mapa contiver um elemento com a chave
key
.fonte
amap.find
retornaamap::end
quando não encontra o que você está procurando - você deve verificar isso.fonte
Verifique o valor de retorno de
find
contraend
.fonte
Você pode criar sua função getValue com o seguinte código:
fonte
out = foundIter->second
out = foundIter->second
ao invés deout = *foundIter
Para resumir sucintamente algumas das outras respostas:
Se você ainda não estiver usando o C ++ 20, poderá escrever sua própria
mapContainsKey
função:Se você deseja evitar muitas sobrecargas para
map
vsunordered_map
e diferentes tipos de chave e valor, pode fazer disso umatemplate
função.Se você estiver usando
C++ 20
ou mais tarde, haverá umacontains
função interna:fonte
Se você deseja determinar se uma chave existe ou não no mapa, você pode usar a função de membro find () ou count () do mapa. A função find que é usada aqui no exemplo retorna o iterador ao elemento ou map :: end, caso contrário. Em caso de contagem, a contagem retornará 1 se for encontrada, caso contrário, retornará zero (ou não).
fonte
O multi-índice de impulso pode ser usado para a solução adequada. A solução a seguir não é a melhor opção, mas pode ser útil em alguns casos em que o usuário está atribuindo valor padrão como 0 ou NULL na inicialização e deseja verificar se o valor foi modificado.
fonte