2017-02-15 67 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