Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Поиск и извлечение элемента отображения



Оператор взятия индекса является простейшим способом извлечения элемента. Например:

// map< string, 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;

map< string, int>:: iterator it = word_count.find( " wrinkles" );

if ( it! = word_count.end() )

count = (*it).second;

Значением итератора является указатель на объект pair, в котором first содержит ключ, а second – значение. (Мы вернемся к этому в следующем подразделе.)

Навигация по элементам отображения

После того как мы построили отображение, хотелось бы распечатать его содержимое. Мы можем сделать это, используя итератор, начальное и конечное значение которого получают с помощью функций-членов begin() и end(). Вот текст функции display_map_text():

void

display_map_text( map< string, loc*> *text_map )

{

typedef map< string, 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 ) {

       if ( loc_cnt )

           cout < < ', ';

       else ++loc_cnt;

 

       cout < < '(' < < (*liter).first

            < < ', ' < < (*liter).second < < ')';

 

       ++liter;

   }

 

   cout < < " )\n";

   ++iter;

}

cout < < endl;

}

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

if ( text_map-> size() )

display_map_text( text_map );

Но более простым способом, без подсчета элементов, будет вызов функции-члена empty():

if (! text_map-> empty() )

display_map_text( text_map );

 

Словарь

Вот небольшая программа, иллюстрирующая построение отображения, поиск в нем и обход элементов. Здесь используются два отображения. Первое, необходимое для преобразования слов, содержит два элемента типа string. Ключом является слово, которое нуждается в специальной обработке, а значением – слово, заменяющее ключ. Для простоты мы задали пары ключ/значение непосредственно в тексте программы (вы можете модифицировать программу так, чтобы она читала их из стандартного ввода или из файла). Второе отображение используется для подсчета произведенных замен. Текст программы выглядит следующим образом:

#include < map>

#include < vector>

#include < iostream>

#include < string>

 

int main()

{

map< string, string > trans_map;

typedef map< string, string >:: value_type valType;

 

// первое упрощение:

// жестко заданный словарь

trans_map.insert( va1Type( " gratz", " grateful" ));

trans_map.insert( va1Type( " 'em", " them" ));

trans_map.insert( va1Type( " cuz", " because" ));

trans_map.insert( va1Type( " nah", " no"   ));

trans_map.insert( va1Type( " sez", " says" ));

trans_map.insert( va1Type( " tanx", " thanks" ));

trans_map.insert( va1Type( " wuz", " was" ));

trans_map.insert( va1Type( " pos", " suppose" ));

 

// напечатаем словарь

map< string, string >:: iterator it;

 

cout < < " Наш словарь подстановок: \n\n";

for ( it = trans_map.begin();

     it! = trans_map.end(); ++it )

cout < < " ключ: " < < (*it).first < < " \t"

      < < " значение: " < < (" it).second < < " \n";

 

cout < < " \n\n";

 

// второе упрощение: жестко заданный текст

string textarray[14]={ " nah", " I", " sez", " tanx",

         " cuz", " I", " wuz", " pos", " to", " not",

         " cuz", " I", " wuz", " gratz" };

 

vector< string > text( textarray, textarray+14 );

vector< string >:: iterator iter;

 

// напечатаем текст

cout < < " Исходный вектор строк: \n\n";

int cnt = 1;

for ( iter = text-begin(); iter! = text.end();

                                 ++iter, ++cnt )

cout < <  *iter < < ( cnt % 8? " " : " \n" );

 

cout < < " \n\n\n";

 

// map для сбора статистики

map< string, int > stats;

typedef map< string, int >:: value_type statsValType;

// здесь происходит реальная работа

for ( iter=text.begin(); iter! = text.end(); ++iter )

if (( it = trans_map.find( *iter ))

       ! = trans_map.end() )

{

if ( stats.count( *iter ))

     stats [ *iter ] += 1;

else stats.insert( statsVa1Type( *iter, 1 ));

*iter = (*it).second;

}

 

// напечатаем преобразованный текст

cout < < " Преобразованный вектор строк: \n\n";

cnt = 1;

for ( iter = text.begin(); iter! = text.end();

                                 ++iter, ++cnt )

cout < < *iter < < ( cnt % 8? " " : " \n" );

cout < < " \n\n\n";

 

// напечатаем статистику

cout < < " И напоследок статистика: \n\n";

map< string, int, less< string>, allocator>:: iterator siter;

 

for (siter=stats.begin(); siter! =stats.end(); ++siter)

cout < < (*siter).first < < " "

    < < " было заменено "

    < < (*siter).second

    < < (" раз(а)\n" );

}

Вот результат работы программы:

 

Наш словарь подстановок:

 

key: 'em value: them

key: cuz value: because

key: gratz value: grateful

key: nah value: no

key: pos value: suppose

key: sez value: says

key: tanx value: thanks

key: wuz value: was

 

 

Исходный вектор строк:

nah I sez tanx cuz I wuz pos

to not cuz I wuz gratz

 

Преобразованный вектор строк:

no I says thanks because I was suppose

to not because I was grateful

 

 

И напоследок статистика:

 

cuz было заменено 2 раз(а)

gratz было заменено 1 раз(а)

nah было заменено 1 раз(а)

pos было заменено 1 раз(а)

sez было заменено 1 раз(а)

tanx было заменено 1 раз(а)

wuz было заменено 2 раз(а)

 

Удаление элементов 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 для каждого примера и укажите наиболее вероятный способ вставки и извлечения элементов.


Поделиться:



Последнее изменение этой страницы: 2019-04-09; Просмотров: 300; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.037 с.)
Главная | Случайная страница | Обратная связь