vectorstring *text_words = text_locations-first;
vectorlocation *text_locs = text_locations-second;
Теперь нам надо синхронно обойти оба вектора, учитывая два случая:
* слово встретилось впервые. Нужно поместить в map новую пару ключ/значение;
* слово встречается повторно. Нам нужно обновить вектор позиций, добавив дополнительную пару (номер строки, номер колонки).
Вот текст функции:
register int elem_cnt = text_words-size();
for ( int ix=0; ix elem_cnt; ++ix )
{
string textword = ( *text_words )[ ix ];
// игнорируем слова короче трех букв
// или присутствующие в списке стоп-слов
if ( textword.size() 3 ||
exclusion_set.count( textword ))
continue;
// определяем, занесено ли слово в отображение
// если count() возвращает 0 - нет: добавим его
if ( ! word_map-count((*text_words)[-ix] ))
{
loc *ploc = new vectorlocation;
ploc-push_back( (*text_locs) [ix] );
word_map-insert(value_type((*text_words)[ix],ploc));
}
else
// добавим дополнительные координаты
(*word_map)[(*text_words)[ix]]-
push_back((*text_locs)[ix]);
}
Синтаксически сложное выражение
(*word_map)[(*text_words)[ix]]-
push_back((*text_locs)[ix]);
будет проще понять, если мы разложим его на составляющие:
// возьмем слово, которое надо обновить
string word = (*text_words) [ix];
// возьмем значение из вектора позиций
vectorlocation *ploc = (*word_map) [ word ];
// возьмем позицию - пару координат
loc = (*text_locs)[ix];
// вставим новую позицию
ploc-push_back(loc);
Выражение все еще остается сложным, так как наши векторы представлены указателями. Поэтому вместо употребления оператора взятия индекса:
string word = text_words[ix]; // ошибка
мы вынуждены сначала разыменовать указатель на вектор:
string word = (*text_words) [ix]; // правильно
В конце концов build_word_map() возвращает построенное отображение:
return word_map;
Вот как выглядит вызов этой функции из main():
int main()
{
// считываем файл и выделяем слова
vectorstring, allocator *text_file = retrieve_text();
text_loc *text_locations = separate_words( text_file );
// обработаем слова
// ...
// построим отображение слов на векторы позиций
mapstring,lос*,lessstring,allocator
*text_map = build_word_map( text_locatons );
// ...
}
6.12.2. Поиск и извлечение элемента отображения
Оператор взятия индекса является простейшим способом извлечения элемента. Например:
// mapstring,int word_count;
int count = word_count[ "wrinkles" ];
Однако этот способ работает так, как надо, только при условии, что запрашиваемый ключ действительно содержится в отображении. Иначе оператор взятия индекса поместит в отображение элемент с таким ключом. В данном случае в word_count занесется пара
string( "wrinkles" ), 0
Класс map предоставляет две операции для того, чтобы выяснить, содержится ли в нем определенное значение ключа.
count(keyValue): функция-член count() возвращает количество элементов с данным ключом. (Для отображения оно равно только 0 или 1). Если count() вернула 1, мы можем смело использовать индексацию:
int count = 0;
if ( word_count.count( "wrinkles" ))
count = word_count[ "wrinkles" ];
*
find(keyValue): функция-член find() возвращает итератор, указывающий на элемент, если ключ найден, и итератор end() в противном случае. Например:
int count = 0;
mapstring,int::iterator it = word_count.find( "wrinkles" );
if ( it != word_count.end() )
count = (*it).second;
*
Значением итератора является указатель на объект pair, в котором first содержит ключ, а second – значение. (Мы вернемся к этому в следующем подразделе.)
6.12.3. Навигация по элементам отображения
После того как мы построили отображение, хотелось бы распечатать его содержимое. Мы можем сделать это, используя итератор, начальное и конечное значение которого получают с помощью функций-членов begin() и end(). Вот текст функции display_map_text():
void
display_map_text( mapstring,loc* *text_map )
{
typedef mapstring,loc* tmap;
tmap::iterator iter = text_map-begin(),
iter_end = text_map-end();
while ( iter != iter_end )
{
cout "word: " (*iter).first " (";
int loc_cnt = 0;
loc *text_locs = (*iter).second;
loc::iterator liter = text_locs-begin(),
liter_end = text_locs-end();
while (liter != liter_end ) {