Como verificar se std :: map contém uma chave sem fazer inserção?

148

A única maneira que eu encontrei para verificar se há duplicatas é através da inserção e verificando a std::pair.secondpara false, mas o problema é que isso ainda insere algo se a chave não é utilizada, enquanto que o que eu quero é uma map.contains(key);função.

jmasterx
fonte

Respostas:

305

Use my_map.count( key ); ele pode retornar apenas 0 ou 1, que é essencialmente o resultado booleano que você deseja.

Como alternativa my_map.find( key ) != my_map.end()também funciona.

Potatoswatter
fonte
40
@ John: Isso cheira a otimização prematura. No GCC (e tenho certeza de sistemas mais razoáveis), map::counté implementado como find(__x) == end() ? 0 : 1;. Para multimapvocê, pode ter um argumento de desempenho, mas essa não é a pergunta da OP e ainda prefiro elegância.
Potatoswatter
42
Não, o argumento de otimização prematuro é válido apenas se a otimização exigir algum esforço, o que, nesse caso, não é necessário.
markh44
13
Não é verdade. Não é prematuro se facilita a leitura do código ou elimina despesas desnecessárias. Nesse caso, se count () for implementado via find () de qualquer maneira, chamar find () eliminará diretamente uma chamada de função ... ergo, é uma otimização madura . Acho que usar a chamada find () também é mais óbvio, mas isso é uma preferência puramente pessoal.
Tim Keating
9
Não é uma otimização prematura estar ciente do desempenho das funções da biblioteca antes de criar o hábito de usá-las. Nesse caso, você está certo, não importa, mas também não faz a minúscula diferença estilística entre encontrar e contar. Acho que você leva a retórica da 'otimização prematura' longe demais. Você deve adotar quaisquer hábitos de otimização "gratuitos" que puder encontrar e usá-los para o desenvolvimento diário. É quando os codificadores sucumbem à armadilha de pagar custos em legibilidade / dev time / etc, tudo por "ganhos de desempenho" não medidos que a retórica prematura da otimização se torna o conselho certo a dar.
VoidStar 24/02
10
Longe, o std deve apenas adicionar uma maldita has(k)/ contains(k)como todas as outras classes de mapas sãos do planeta. Design de interface ruim. A abordagem find () é muito detalhada e count(k)definitivamente não está em paridade semântica com has(k). Para esse assunto também não é find(k). Confira a contagem de visualizações desta pergunta.
Jarrod Smith
46

A resposta de Potatoswatter está bem, mas prefiro usar findou lower_boundnão. lower_boundé especialmente útil porque o iterador retornado pode ser usado posteriormente para uma inserção sugerida, caso você deseje inserir algo com a mesma chave.

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
fonte
Isso é sutilmente diferente de como ele diz que está fazendo isso ... a única diferença é que o cálculo de valuepode ser ignorado se a inserção for desnecessária.
Potatoswatter 07/10/10
1
Claro, eu entendo que o OP não quer inserir, portanto, uma lower_boundsolução baseada em excesso é um exagero. Eu meio que acabei de mencionar minha resposta "por completude"; como eu disse, o seu é perfeitamente adequado. :-)
Chris Jester-Young
4
Sim, esta é uma boa resposta e não discordo de nada. Apenas apontando a relação com a alternativa inserta priori. Na verdade, há outra diferença se, usando a multimap, o lower_boundmétodo é inserido no início do intervalo equivalente, enquanto o insertmétodo simples é adicionado ao final do intervalo.
Potatoswatter 07/10/10
2
Não é a resposta para a pergunta, mas minha pergunta ruim me leva à resposta correta aqui ... Preciso fazer a inserção / atualização. : D
Hunter-Orionnoir
1
@ Hunter Você pode me mostrar seu código? Se não for grande, provavelmente posso analisá-lo para você.
Chris Jester-Young
8

Seu desiderato map.contains(key)está agendado para o rascunho do padrão C ++ 2a . Em 2017, foi implementado pelo gcc 9.2 . Também está no clang atual .

Camille Goudeseune
fonte
Esse é um ótimo recurso! Eu acho que ele pousou em C ++ 20. cppreference.com
Franklin Yu