将字值转换为具有设定值的键映射

Word value into a key map which has set value

本文关键字:映射 转换      更新时间:2023-10-16

我知道map是什么以及它的一般基本功能,但我不知道为什么这里使用set而不是仅仅声明int i = value或类似的东西。

我真正想做的是:将单词放入向量后,我想使用相同的单词作为值的键。但是我真的不知道用map来做这个的全部目的。不确定我是否给了足够的信息,但只是问你需要更多,我会回答。

我只提供了一个readWords函数,但如果有人需要完整的代码,包括头文件,类和主文件,那么我也可以把它们放上去。

我部分有代码写在那里,有帮助,但我真的不知道它在push_back()函数之后做什么。

/* Read word-by-word from filename and store words in text vector.
* Also use normalized version of word as key in concordance map
* The value associated with each key in the map is a set whose
* keys are the associated indices into the vector.
*/
void Concordance::readWords(char * filename){
    ifstream fin(filename, ifstream::in);
    if (fin.is_open()){
        while(!fin.eof()){
            string word;
            fin >> word;
            normalize(word);
            text.push_back(word); //puts word into vector
            set<int> seat;
            seat.insert(text.size()-1);
            pair<string, set<int> > pear;
            concordance.insert(pear);
        }
    }
    else{
        cerr << "Unable to open file datafile.txt";
        exit(1);   // call system to stop
    }
    fin.close(); //closes the filename
}

我认为你没有完全理解这个算法的要求。(顺便问一下,这是家庭作业吗?)

这里的目标是生成一个一致性——每个单词出现的所有列表。set的作用是保存所有的出现。例如:"苹果"这个词可能出现在第1页、73页和100页。因此,"apple"的映射条目必须包含所有这些值。)

规范化的目的是为了节省读者的检索时间:"apple"、"apple"answers"apples"应该可能都在地图的一个条目中。

理解了这一点,我们可以更新你的程序。

首先,在读取数据之前不要检查eof 。只有在读取数据后进行检查才有意义。实际上,对于这种检查有一个更简单的习惯用法:

string word;
while (fin >> word) {
    ...
在我看来,我们需要在vector中存储原始单词,然后使用规范化的单词作为映射索引
text.push_back(word);
normalize(word);

现在,更新地图很容易。您不需要pair,只需使用[]运算符即可。要认识到,仅仅引用一个地图条目就会导致它突然出现!

concordance[word].insert(text.size()-1);

EDIT将最后一位分开:

concordance[word]在map中查找由word索引的条目。如果条目存在,则返回它。如果条目没有退出,则创建它,并返回新形成的条目。.insert是对由word索引的map表项所在的set进行的插入操作。text.size()-1是插入到由word索引的map表项所在的set中的值。

将它们重新组合在一起,concordance[word].insert(text.size()-1)查看映射,检索(或创建)指定的set,然后将数字text.size()-1插入该集合。

好了!

我不确定您是否在复制代码时犯了错误,或者代码是否故意这样做,但不使用seat集(除了插入元素之外,但由于它不是读取/存储它将丢失),并且添加到concordance的所有元素将是对("",[empty set])

不,它看起来像是在尝试建立一个索引,即从单词映射到单词在向量中出现的位置。如果是这种情况,那么按照以下方式执行可能会更好:

std::map<std::string, std::set<int> > concordance;
//...
concordance[word].insert(text.size()-1); // if it does not exists, it will create it
                                         // if it exists it will retrieve it and
                                         // add the new position

此模式通常用于将单词索引到页面中(例如,对于一本书),其中集合比向量具有优势,它可以保证唯一性,如果一个单词在单个页面中出现100次,则集合将确保页码不重复(您必须在向量中进行测试)。代码中的情况并非如此,因为索引指向的是单词向量中的位置,这些位置本身是唯一的。

也要注意,正如Nawaz指出的,这个循环需要一些修正

首先,您的while循环是错误的,因为eof标志(或任何其他失败标志)在之后设置,试图从流中读取失败;这意味着,如果尝试读取失败,则尝试将先前读取的word插入vector两次,而循环中的其余代码在实际上不应该执行时仍然执行。

一个更习惯的while循环是这样的:

string word;
while( fin >> word ){
   normalize(word);
   text.push_back(word); //puts word into vector
   set<int> seat;
   seat.insert(text.size()-1);
   pair<string, set<int> > pear;
   concordance.insert(pear);
}

如果尝试读取(即fin >> word)失败,则返回的std::istream&隐式转换为false,并退出循环。

我没有很清楚地理解你的帖子的其余部分,这个问题以及你到底想做什么,所以我不能评论。