2017-02-15 5 views
-2

Ich versuche, ein Programm zu schreiben, das Liste der Zeichenfolgen als Eingabe nimmt und Hash-Tabelle mit Zeichenfolge-Name und seiner Position erstellt.C++ unordered_map in Vektor einfügen

Beispiel:
Vektorwörter {"first", "second", "third", "her", "second"};

Ausgang:
zuerst 1
zweite 2,5
dritte 3
hervor 4

ich zwei Probleme bin vor bitte unter ihnen im Code Kommentar zu finden.
Bitte sagen Sie mir, was mache ich falsch?

int main() 
{ 
    vector<string> words {"first", "second", "third", "forth", "second"}; 

    unordered_map<string, vector<int>> hash_table; 
    unordered_map<string, vector<int>>::const_iterator hash_it; 

    int loc = 1; 

    for(auto n = words.begin(); n != words.end(); ++n){ 
     hash_it = hash_table.find(*n); 
     if(hash_it == hash_table.end()) 
      hash_table.insert(make_pair(*n, vector<int> (loc))); 
     else 
      //hash_it->second.push_back(loc); //Problem 1 - this statement gives error 

     ++loc; 
    } 

    for(auto& n:hash_table){ 
     cout<<"Word - "<<n.first<<" Loc -"; 
     vector<int> tmp1 = n.second; 
     for(auto j = tmp1.begin(); j != tmp1.end(); ++j) 
      cout<<" "<<*j; 
     cout<<endl; 
    } 
} 

Problem 2 - Lage sind Werte von 0
Ausgabe von Programm -
Wort - her Loc - 0
Wort - dritter Loc - 0
Wort - zweite Loc - 0
Wort - erster Loc - 0

+1

Willkommen Überlauf zu stapeln. Bitte nehmen Sie sich die Zeit, [Die Tour] zu lesen (http: // stackoverflow.com/tour) und beziehen Sie sich auf das Material aus der [Hilfe] (http://stackoverflow.com/help/asking) was und wie Sie hier fragen können. –

+1

Welcher Fehler genau wurde Kompilierung fehlgeschlagen? –

+0

@ABusyProgrammer Fehler war - In der Funktion 'int main()': 23:42: Fehler: Übergabe 'const std :: Vektor ' als 'dieses' Argument von 'void std :: Vektor <_Tp, _Alloc> :: push_back (const value_type &) [mit _Tp = int; _Alloc = std :: Zuordner ; std :: vector <_Tp, _Alloc> :: value_type = int] 'discards qualifiers [-fpermissive] – cplusplusnoob

Antwort

3

Sie das Problem zu kompliziert, operator[] auf der Karte oder unordered_map sind speziell für solche Fälle geschaffen:

int loc = 1; 
for(auto n = words.begin(); n != words.end(); ++n) 
    hash_table[*n].push_back(loc++); 

das ist alles Code, den Sie brauchen. Sie können es für Bereich Schleife machen noch einfacher mit:

int loc = 1; 
for(const auto &word: words) 
    hash_table[word].push_back(loc++); 
+0

Vielen Dank Slava, das spart eine Menge Mühe und es ist ziemlich einfach, jetzt funktioniert der Code perfekt. – cplusplusnoob

3

Das erste Problem ist, dass Sie const_iterator verwenden, wo Sie iterator verwendet werden soll. Sie können das Element, auf das sich const_iterator bezieht, nicht ändern.

Verwenden Sie unordered_map<string, vector<int>>::iterator hash_it; anstelle von unordered_map<string, vector<int>>::const_iterator hash_it;. Besser noch, verwenden Sie auto, um den zu verwendenden Typ automatisch abzuleiten.

for (auto n = words.begin(); n != words.end(); ++n) { 
    auto hash_it = hash_table.find(*n); 
// ^^^^ Deduce the correct type 
    if (hash_it == hash_table.end()) 
     hash_table.insert(make_pair(*n, vector<int>(loc))); 
    else 
     hash_it->second.push_back(loc); //No problem 

     ++loc; 
} 

Das zweite Problem ist, dass die Aussage vector<int>(loc) einen Vektor enthält loc Werte macht, kein Vektor nur loc enthält. Die einfachste Änderung besteht darin, stattdessen vector<int>(1, loc) zu verwenden, wodurch 1 Wert gleich loc wird.

for (auto n = words.begin(); n != words.end(); ++n) { 
    auto hash_it = hash_table.find(*n); 
// ^^^^ Deduce the correct type 
    if (hash_it == hash_table.end()) 
     hash_table.insert(make_pair(*n, vector<int>(1, loc))); 
    else 
     hash_it->second.push_back(loc); //Problem 1 - this statement gives error 

    ++loc; 
} 

Wie andere haben darauf hingewiesen, können Sie sich eine Menge Ärger sparen, indem operator[] verwenden. Eine einfachere Methode dazu finden Sie unter this answer von Slava.

+0

Vielen Dank François. Ich habe seinen konstanten Iterator nicht erkannt, jetzt verstehe ich, warum diese Zeile nicht funktioniert hat. Das ist eine große Hilfe! – cplusplusnoob

0

Sie könnten den Code effizienter machen, wenn Sie eine ungeordnete_Multimap verwenden. Sie brauchen dann keinen Vektor für die Positionen. Dies funktioniert, weil Elemente mit demselben Schlüssel garantiert in fortlaufender Reihenfolge sind.

int main() 
{ 
    vector<string> words {"first", "second", "third", "forth", "second"}; 

    unordered_multimap< string, size_t > hash_table; 

    size_t loc = 0; 
    for(const auto& word : words) 
    { 
     hash_table.insert(make_pair(word, ++loc)); 
    } 

    for(auto i = hash_table.begin(), j = hash_table.begin(); 
     i != hash_table.end(); 
     i = j) 
    { 
     cout << "Word - "<< i->first << " Loc -"; 

     // Iterate over all elements with same key 
     do 
     { 
      cout << " " << j->second; 
      ++j; 
     } 
     while(j != hash_table.end() && j->first == i->first); 

     cout << endl; 
    } 

    return 0; 
} 

Wenn Sie nur die Standorte eines bestimmten Wort nachschlagen möchten, würden Sie unordered_map :: equal_range() wie folgt aus:

cout << "Locations of 'second':"; 
auto rng = hash_table.equal_range("second"); 
for(auto i = rng.first; i != rng.second; ++i) 
    cout << " " << i->second; 
+0

bitte verzeihen Sie meinen Mangel an Wissen, aber was macht size_t? speichert es irgendeine Art von Informationen? – cplusplusnoob

+0

size_t wird normalerweise als vorzeichenloser Integertyp definiert, hängt jedoch von der Plattform ab. Wenn Sie für 64-Bit kompilieren, ist size_t in der Regel auch 64-Bit, während eine ganze Zahl (zumindest unter Windows) immer noch 32-Bit und somit nicht ausreichen würde, um einen Index eines Vektors ohne Überlauf zu speichern. Dies ist der Grund, warum dieser Datentyp von allen Standardcontainern als Rückgabetyp der Methode size() verwendet wird. – zett42

+0

Ich habe mein Beispiel korrigiert, um size_t als Datentyp der Variablen 'loc' zu verwenden. Bei 5 Einträgen des Wortvektors ist das natürlich nicht wichtig, aber beachte einen sehr großen Vektor mit mehr als 2^31 Wörtern ... in diesem Fall könnte die 'int loc' bereits überlaufen. – zett42