Значение слова в карте ключей, которая имеет заданное значение - PullRequest
0 голосов
/ 04 мая 2011

Я знаю, что такое 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
}

Ответы [ 3 ]

2 голосов
/ 04 мая 2011

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

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

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

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

Во-первых, никогда не проверяйте 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 голос
/ 04 мая 2011

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

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

0 голосов
/ 04 мая 2011

Прежде всего, ваш цикл 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::istream& неявно преобразуется в false, и цикл завершается.

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

...