2012-01-28 5 views
10

Il multimap in C++ sembra funzionare davvero strano, vorrei sapere perchéunordered_multimap - iterare il risultato di find() produce elementi con valore diverso

#include <iostream> 
#include <unordered_map> 

using namespace std; 

typedef unordered_multimap<char,int> MyMap; 

int main(int argc, char **argv) 
{ 
    MyMap map; 
    map.insert(MyMap::value_type('a', 1)); 
    map.insert(MyMap::value_type('b', 2)); 
    map.insert(MyMap::value_type('c', 3)); 
    map.insert(MyMap::value_type('d', 4)); 
    map.insert(MyMap::value_type('a', 7)); 
    map.insert(MyMap::value_type('b', 18)); 

    for(auto it = map.begin(); it != map.end(); it++) { 
     cout << it->first << '\t'; 
     cout << it->second << endl; 
    } 

    cout << "all values to a" << endl; 
    for(auto it = map.find('a'); it != map.end(); it++) { 
     cout << it->first << '\t' << it->second << endl; 
    } 

} 

questo è l'output:

c 3 
d 4 
a 1 
a 7 
b 2 
b 18 
all values to a 
a 1 
a 7 
b 2 
b 18 

perché l'output contiene ancora qualcosa con b come chiave quando sto chiedendo esplicitamente "a"? È un compilatore o un bug di stl?

risposta

36

find, come implementato, restituisce un iteratore per il primo elemento che corrisponde alla chiave nella multimap (come con qualsiasi altra mappa). È molto probabile che alla ricerca di equal_range:

// Finds a range containing all elements whose key is k. 
// pair<iterator, iterator> equal_range(const key_type& k) 
auto its = map.equal_range('a'); 
for (auto it = its.first; it != its.second; ++it) { 
    cout << it->first << '\t' << it->second << endl; 
} 
+0

Se si cambia -> a. allora accetterò la tua risposta. – Arne

+1

Ho ottenuto '->' felice. – user7116

-1

Sembrerebbe che si ottiene un iteratore in pieno a "lista" di coppie, a partire dalla prima coppia con 'a' come è fondamentale. Quindi, quando si itera fino alla fine, naturalmente si otterrà anche tutto oltre "a". Se cercavi "c", probabilmente dovresti scorrere l'intera "lista" facendo ciò che fai lì. Forse dovresti iterare su "it! = Map.end() & & it-> first == 'a'" se vuoi tutte le a's.

8

Questo non è un bug, è di progettazione. find restituisce un iteratore a uno degli elementi corrispondenti, tutto qui. Continuerai a scorrere fino alla fine della mappa con il tuo costrutto.

È necessario utilizzare multimap::equal_range per eseguire ciò che si desidera.

4

C'è un esempio in www.cplusplus.com, su Come utilizzare il metodo equal_range per ottenere tutti gli elementi che hanno la stessa chiave.

// unordered_multimap::equal_range 
#include <iostream> 
#include <string> 
#include <unordered_map> 
#include <algorithm> 

typedef std::unordered_multimap<std::string,std::string> stringmap; 

int main() 
{ 
    stringmap myumm = { 
    {"orange","FL"}, 
    {"strawberry","LA"}, 
    {"strawberry","OK"}, 
    {"pumpkin","NH"} 
    }; 

    std::cout << "Entries with strawberry:"; 
    auto range = myumm.equal_range("strawberry"); 
    for_each (
    range.first, 
    range.second, 
    [](stringmap::value_type& x){std::cout << " " << x.second;} 
); 

    return 0; 
} 

Si prega di fare riferimento al link: http://www.cplusplus.com/reference/unordered_map/unordered_multimap/equal_range/

+0

@einpoklum Questa è ** una risposta ** prima di eliminare per favore leggi questa meta [stai facendo-sbagliato-a-plea-per-sanità-in-bassa-qualità-posts-coda] (http://meta.stackoverflow.com/questions/287563/youre-doing-it-wrong-a-plea-for-sanity-in-the-low-quality-posts-queue) –

+0

Lasciatemi riformulare (il meccanismo di revisione non funziona Ti lasciamo fare commenti specifici e stai scegliendo da una lista): OP ha chiesto "Perché X succede?" - la tua risposta, anche se probabilmente utile in generale, non è una spiegazione di ciò che accade con il codice OP. Quindi, non una risposta. – einpoklum