Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
8
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

6.12.5. Удаление элементов map

Существуют три формы функции-члена erase() для удаления элементов отображения. Для единственного элемента используется erase() с ключом или итератором в качестве аргумента, а для последовательности эта функция вызывается с двумя итераторами. Например, мы могли бы позволить удалять элементы из text_map таким образом:

string removal_word;

cout << "введите удаляемое слово: ";

cin >> removal_word;

if ( text_map->erase( remova1_word ))

cout << "ok: " << remova1_word << " удалено\n";


else cout << "увы: " << remova1_word << " не найдено!\n";

Альтернативой является проверка: действительно ли слово содержится в text_map?

map<string,loc*>::iterator where;

where = text_map.find( remova1_word );

if ( where == text_map->end() )

cout << "увы: " << remova1_word << " не найдено!\n";

else {

text_map->erase( where );

cout << "ok: " << remova1_word << " удалено!\n";


}

В нашей реализации text_map с каждым словом сопоставляется множество позиций, что несколько усложняет их хранение и извлечение. Вместо этого можно было бы иметь по одной позиции на слово. Но контейнер map не допускает дублирующиеся ключи. Нам следовало бы воспользоваться классом multimap, который рассматривается в разделе 6.15.

Упражнение 6.20

Определите отображение, где ключом является фамилия, а значением – вектор с именами детей. Поместите туда как минимум шесть элементов. Реализуйте возможность делать запрос по фамилии, добавлять имена и распечатывать содержимое.

Упражнение 6.21

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

Упражнение 6.22

Приведите хотя бы три примера, в которых нужно использовать отображение. Напишите определение объекта map для каждого примера и укажите наиболее вероятный способ вставки и извлечения элементов.

6.13. Построение набора стоп-слов

Отображение состоит из пар ключ/значение. Множество (set), напротив, содержит неупорядоченную совокупность ключей. Например, бизнесмен может составить “черный список” bad_checks, содержащий имена лиц, в течение последних двух лет присылавших фальшивые чеки. Множество полезно тогда, когда нужно узнать, содержится ли определенное значение в списке. Скажем, наш бизнесмен, принимая чек от кого-либо, может проверить, есть ли его имя в bad_checks.

Для нашей поисковой системы мы построим набор стоп-слов – слов, имеющих семантически нейтральное значение (артикли, союзы, предлоги), таких, как the, and, into, with, but и т.д. (это улучшает качество системы, однако мы уже не сможем найти первое предложение из знаменитого монолога Гамлета: “To be or not to be?”). Прежде чем добавлять слово к word_map, проверим, не содержится ли оно в списке стоп-слов. Если содержится, проигнорируем его.

6.13.1. Определение объекта set и заполнение его элементами

Перед использованием класса set необходимо включить соответствующий заголовочный файл:

#include <set>

Вот определение нашего множества стоп-слов:

set<string> exclusion_set;

Отдельные элементы могут добавляться туда с помощью операции insert(). Например:

exclusion_set.insert( "the" );


exclusion_set.insert( "and" );

Передавая insert() пару итераторов, можно добавить целый диапазон элементов. Скажем, наша поисковая система позволяет указать файл со стоп-словами. Если такой файл не задан, берется некоторый набор слов по умолчанию:

typedef set< string >::difference_type diff_type;

set< string > exclusion_set;

ifstream infile( "exclusion_set" );

if ( ! infile )

{

static string default_excluded_words[25] = {

"the","and","but","that","then","are","been",

"can"."can't","cannot","could","did","for",

"had","have","him","his","her","its","into",

"were","which","when","with","would"

};

cerr << "предупреждение! невозможно открыть файл стоп-слов! -- "

<< "используется стандартный набор слов \n";

copy( default_excluded_words, default_excluded_words+25,

inserter( exclusion_set, exclusion_set.begin() ));

}

else {

istream_iterator<string,diff_type> input_set(infile),eos;

copy( input_set, eos, inserter( exclusion_set,

exclusion_set.begin() ));


}

В этом фрагменте кода встречаются два элемента, которые мы до сих пор не рассматривали: тип difference_type и класс inserter. difference_type – это тип результата вычитания двух итераторов для нашего множества строк. Он передается в качестве одного из параметров шаблона istream_iterator.

copy() –один из обобщенных алгоритмов. (Мы рассмотрим их в главе 12 и в Приложении.) Первые два параметра – пара итераторов или указателей – задают диапазон. Третий параметр является либо итератором, либо указателем на начало контейнера, в который элементы копируются.

Проблема с этой функцией вызвана ограничением, вытекающим из ее реализации: количество копируемых элементов не может превосходить числа элементов в контейнере-адресате. Дело в том, что copy() не вставляет элементы, она только присваивает каждому элементу новое значение. Однако ассоциативные контейнеры не позволяют явно задать размер. Чтобы скопировать элементы в наше множество, мы должны заставить copy() вставлять элементы. Именно для этого служит класс inserter (детально он рассматривается в разделе 12.4).