2017-02-15 59 views
-2

我想編寫一個程序,它將字符串列表作爲輸入,並創建帶有字符串名稱和位置的哈希表。矢量詞{「first」,「second」,「third」,「fourth」,「second」};以及其他數據。C++ unordered_map插入到向量

輸出:
第1
第二2,5
第三3
提出4

我面臨兩個問題,請找到它們在下面的代碼註釋。
請告訴我我做錯了什麼?

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; 
    } 
} 

問題2 - 位置的值是節目0
輸出 -
字 - 所述祿 - 0
字 - 第三祿 - 0
字 - 第二祿 - 0
字 - 第一祿 - 0

+1

歡迎堆棧溢出。請花些時間閱讀[The Tour](http:// stackoverflow。com/tour),並參考[幫助中心](http://stackoverflow.com/help/asking)中的內容以及您可以在此處詢問的內容。 –

+1

編譯失敗到底是什麼錯誤? –

+0

@ABusyProgrammer錯誤是 - 在函數 '詮釋主()': 23點42:錯誤:使 '常量性病::矢量' 作爲 '這個' 的「無效參數的std ::矢量<_Tp, _Alloc> ::的push_back(常量VALUE_TYPE& )[with _Tp = int; _Alloc = std :: allocator ; std :: vector <_Tp, _Alloc> :: value_type = int]'丟棄限定符[-fpermissive] – cplusplusnoob

回答

3

你過於複雜的問題,operator[]地圖或unordered_map針對這種情況專門設立:

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

這就是你需要的所有代碼。您可以使用範圍循環,使其更簡單:

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

非常感謝Slava,這節省了大量的精力,而且非常簡單,現在代碼完美無缺。 – cplusplusnoob

3

第一個問題是您正在使用const_iterator,你應該使用iterator。您不能修改const_iterator所指的元素。使用代替unordered_map<string, vector<int>>::const_iterator hash_it;。更好的是,使用auto來自動推斷使用的類型。

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; 
} 

的第二個問題是,語句vector<int>(loc)使含有loc值,僅含有loc不是矢量的矢量。最簡單的更改是使用vector<int>(1, loc),這會使1值等於loc

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; 
} 

正如其他人所指出的那樣,你可以通過使用operator[]爲自己省下不少麻煩。請參閱Slava的this answer,以獲取更簡單的方法。

+0

非常感謝François。我沒有意識到它的const iterator,現在我明白了爲什麼那行不起作用。這非常有幫助! – cplusplusnoob

0

如果您使用unordered_multimap,則可以使代碼更高效。那麼你不需要一個向量。 這是有效的,因爲具有相同鍵的元素保證連續順序。

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; 
} 

如果只想查找特定單詞的位置,你會使用unordered_map :: equal_range()這樣的:

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

請原諒我缺乏知識,但size_t做什麼?它是否存儲任何類型的信息? – cplusplusnoob

+0

size_t通常定義爲無符號整數類型,但它取決於平臺。在編譯64位時,size_t通常也是64位,而整數(至少在Windows下)仍然是32位,因此不足以存儲沒有溢出的向量的索引。這就是爲什麼這個數據類型被所有標準容器用作size()方法的返回類型的原因。 – zett42

+0

我修正了我的例子,使用size_t作爲'loc'變量的數據類型。有5個詞的向量這當然不重要,但考慮一個超過2^31個字的非常大的向量......在這種情況下,'int loc'可能已經溢出。 – zett42