在使用映射中的向量时出现错误

3

我正试图将向量添加到地图中与键相对应的位置。

vector<string> words;
map<string, vector<string>> wordMap;

for (int i = 0; i < words.size(); i++) {
    string word = words.at(i);

    if (wordMap.find(word) == wordMap.end())
        wordMap.insert(make_pair(word, vector<string>()));

    vector<string> context = { "EMPTY" };

    if (i == 0)
        context = { "Beginning of words", words[i + 1], words[i + 2] };
    else if(i == 1)
        context = { "Beginning of words", words[i - 1], words[i + 1], words[i + 2] };
    else if (i == words.size() - 2)
        context = { words[i - 2], words[i - 1], words[i + 1], "End of words" };
    else if(i == words.size() - 1)
        context = { words[i - 2], words[i - 1], "End of words" };
    else
        context = { words[i - 2], words[i - 1], words[i + 1], words[i + 2] };

    wordMap[word].push_back(context);
    cout << context[0] << endl;
}

我一直在这个位置收到以下错误:

wordMap[word].push_back(context);

Error: no instance of overloaded function "std::vector<_Ty,_Alloc>::push_back[with_Ty=std::string,_Alloc=std::allocator<std::string>]" matches the argument list 
argument types are: (std::vector<std::string, std::allocator<std::string>>) 
object type is std::vector<std::string, std::allocator<std::string>>

程序中的其他部分都可以正常运行,如果需要我可以将其发布,但是唯一的错误就是当我尝试使用push_back时。我需要使用push_back因为我无法重新分配值。我必须保留位于该键上的所有先前值,因此push_back是理想的选择。非常感谢您的帮助。


1
你觉得使用'wordMap[word] = context'代替'wordMap[word].push_back(context)'可行吗?或者你能否更清楚地说明你想要实现什么? - marco6
1
哦,我看错了。你试图将一个 vector<string> 推入到另一个 vector<string> 中。你需要一个字符串作为参数。你能把 context 定义成 stringstream,随着进程的进行添加内容,然后只需执行 wordMap[word].push_back(context.str()); 即可吗? - RyanP
@RyanP 基本上,我正在将大量文本分离成一个映射,以便每个单词都可以分开。这消除了重复项,但向量用于保存关键字之前和之后的两个单词。因此,我需要将该单词的新“上下文”推入映射值中。 - Dillon Clapp
2
std::copy(context.begin(), context.end(), std::back_inserter(wordMap[word])); 应该可以完成此操作 (需要包含头文件 #include <iterator>#include <algorithm>)。 - Max Lybbert
2
请注意,带有wordMap.find(word) ...的代码是完全多余的,可以删除。 - Slava
显示剩余2条评论
2个回答

10

改为:

wordMap[word].push_back(context);

你应该添加新向量:

std::copy(context.begin(), context.end(), std::back_inserter(wordMap[word]));

另一件事是,您实际上并不需要这个初始化:

if (wordMap.find(word) == wordMap.end())
        wordMap.insert(make_pair(word, vector<string>()));

稍后wordMap[word]将添加值初始化的元素。

当在map实例上调用operator[]时,如果给定键没有值,则总是会添加一个新元素,然后返回对它的引用。



-1
编辑: 问题出在wordMap[word]的类型是vector<string>,调用push_back是正确的,但你需要提供一个字符串类型的值来进行push_back,而这里wordMap[word].push_back(context);context的类型是vector<string>
也许可以这样修改:
for(vector<string>::iterator iter = context.begin(); iter != context.end(); iter++) {
    wordMap[word].push_back(*iter);
}

此外,我建议使用指针,因为将字符串向量的指针存储在堆中可能比存储在栈中更好。例如:
map<string, vector<string>*> wordMap;
...
vector<string>* context = new vector<string>();
...
wordMap[word] = context;

这可能会变得混乱起来,因为您必须确保 map 的析构函数正确处理向量。否则,您将不得不单独跟踪它们,然后必须两次存储相同的信息。 - Lilith Daemon
好的,地图析构函数不会销毁向量,你必须在地图被销毁之前在类析构函数中释放它们。因此,持有地图的父类或函数应该销毁地图中的所有向量。 - ArmenB
至少应该这样写:wordMap[word] = context,因为 map 没有 push_back 方法。但我永远不会这样做,而且这也不能解决我所理解的问题。 - marco6
没错,我修复了它。这可能不能解决问题,但这是我以前使用过并且效果很好的一种方法,因为现在它使用堆而不是栈,所以有更多的空间,并且保持对向量的本地引用更容易实现。这种方法没有任何问题,只是另一种做事情的方式。 - ArmenB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接