Значение слова в сопоставление ключей, имеющее заданное значение

#c #stl #map #set

#c #stl #словарь #установить

Вопрос:

Я знаю, что такое map и его общие базовые функции, но я не знаю, почему здесь используется a 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
}
  

Ответ №1:

Я не думаю, что вы полностью понимаете требования к этому алгоритму. (Кстати, это домашнее задание?)

Цель здесь состоит в том, чтобы создать соответствие — список всех вхождений каждого слова. Цель set состоит в том, чтобы сохранить все вхождения. (Например: слово «apple» может появиться на страницах 1, 73 и 100. Таким образом, запись в сопоставлении для «apple» должна содержать все эти значения.)

Цель нормализации состоит в том, чтобы сэкономить читателю время согласования: «apple», «Яблоко» и «apples», вероятно, должны быть в одной записи на карте.

Понимая это, мы можем обновить вашу программу.

Во-первых, никогда не проверяйте, eof прежде чем читать данные. Имеет смысл проверять это только после того, как вы прочитаете данные. На самом деле, существует гораздо более простая идиома для этой проверки:

 string word;
while (fin >> word) {
    ...
  

Мне кажется, что от нас требуется сохранить исходное слово в векторе, а затем использовать нормализованное слово в качестве индекса сопоставления

 text.push_back(word);
normalize(word);
  

Теперь обновить сопоставление проще простого. Вам не нужен pair , просто используйте [] оператор. Поймите, что простая ссылка на запись карты приводит к ее появлению!

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

РЕДАКТИРОВАТЬ, разбивая этот последний бит на части:

concordance[word] ищет запись, проиндексированную word в сопоставлении. Если запись существует, она возвращается. Если запись не завершается, она создается, и возвращается вновь сформированная запись. .insert это операция вставки в набор, расположенный рядом с элементом карты, индексируемым word . text.size()-1 это значение, вставленное в набор, расположенный в записи карты, проиндексированной word .

Собирая его обратно, concordance[word].insert(text.size()-1) просматривает сопоставление, извлекает (или создает) указанное set , а затем вставляет число text.size()-1 в этот набор.

Вот так!

Комментарии:

1. Итак, согласование [word].insert(text.size() -1); вставляет ли ‘word’ в сопоставление согласований, а затем вставляет размер текста? Мне также не нужно объявлять новый набор?

2. Да, concordance[word].insert(text.size()-1); это вставка word в сопоставление совпадений, а затем вставка text.size()-1 в набор. Вам не нужно объявлять новый набор.

3. Спасибо за подробное объяснение! Я бы проголосовал за вас, если бы мог. 😀

Ответ №2:

Я не уверен, допустили ли вы ошибку при копировании кода, или код был преднамеренно таким, но 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 раз на одной странице, набор гарантирует, что номер страницы не повторяется (вам придется проверить это в векторе). Это не относится к коду, поскольку индексы относятся к позициям в векторе слов, которые уникальны сами по себе.

Также обратите внимание, как указывает Наваз, что цикл нуждается в некоторых исправлениях.

Ответ №3:

Прежде всего, ваш while цикл неправильный, потому что eof флаг (или любой другой флаг сбоя) устанавливается после неудачной попытки чтения из потока; это означает, что если попытка чтения завершается неудачей, вы пытаетесь вставить ранее прочитанное word в вектор дважды, а остальной код в цикле все еще выполняется, хотя на самом деле не должен.

Более идиоматичным циклом 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::istreamamp; неявно преобразуется в false , и цикл завершается.

И я не совсем понял остальную часть вашего поста, вопрос и что именно вы пытаетесь сделать, поэтому я не могу это комментировать.