The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа

11.3. Словари (map).

Словари предназначены для хранения произвольного количества элементов, в виде пар "ключ-значение". Причем к "ключам" предъявляется требование уникальности. Словари обладают широкими возможностями доступа к произвольным элементам и незначительными накладными расходами на операцию добавления нового элемента. Если в словарь вставляется новое значение по существующему ключу, то оно затирает старое значение в паре "ключ-значение".

Рисунок 11.3. Словарь экземпляров класса Film.


Поскольку словари хранят элементы в виде "ключ-значение", то принципы работы со словарями несколько отличаются от тех, что используются при работе со списками и векторами. Ниже приводится версия класса Film, которая будет использоваться для иллюстрации работы со словарем:
class Film 
{ 
public: 
  Film(const QString &title = "", int duration = 0); 
  
  QString title() const { return myTitle; } 
  void setTitle(const QString &title) { myTitle = title; } 
  int duration() const { return myDuration; } 
  void setDuration(int minutes) { myDuration = minutes; } 
  
private: 
  QString myTitle; 
  int myDuration; 
};

Film::Film(const QString &title, int duration) 
{ 
  myTitle = title; 
  myDuration = duration; 
}
      
В этой версии отсутствует числовой идентификатор фильма, поскольку теперь он будет использоваться в качестве "ключа" в словаре. Кроме того, здесь отсутствуют операторы сравнения -- словари изначально упорядочивают элементы по ключу, но не по значению.

Класс словаря в STL определен под именем std::map<K, T>, в файле заголовка <map>. Ниже приводится пример объявления словаря, с целыми значениями в качестве ключей и Film -- в качестве значения:

  map<int, Film> films;
      
Эквивалент в Qt -- QMap<K, T>:
  QMap<int, Film> films;
      
Наиболее естесственный способ заполнения словарей -- присваивать значение по заданному ключу:
  films[4812] = Film("A Hard Day's Night", 85); 
  films[5051] = Film("Seven Days to Noon", 94); 
  films[1301] = Film("Day of Wrath", 105); 
  films[9227] = Film("A Special Day", 110); 
  films[1817] = Film("Day for Night", 116);
      
Итератор словаря предоставляет возможность доступа к паре "ключ-значение". Ключ извлекается с помощью (*it).first, а значение -- (*it).second:
  map<int, Film>::const_iterator it = films.begin(); 
  while (it != films.end()) { 
    cerr << (*it).first << ": " 
         << (*it).second.title().ascii() << endl; 
    ++it; 
  }
      
Большинство компиляторов допускают запись в виде it->first и it->second, но более переносимый вариант, все таки: (*it).first и (*it).second.

Итераторы словарей в Qt несколько отличаются от итераторов словарей в STL. В Qt ключ можно получить с помощью it.key(), а значение -- it.data():

  QMap<int, Film>::const_iterator it = films.begin(); 
  while (it != films.end()) { 
    cerr << it.key() << ": " << it.data().title().ascii() < endl; 
    ++it; 
  }
      
При обходе словаря в цикле, элементы словаря всегда упорядочены по значению ключа.

Для доступа к значениям словаря и их изменения может использоваться оператор "[ ]", однако, при попытке получить значение по несуществующему в словаре ключу, будет создан новый элемент словаря с заданным ключом и пустым значением. Чтобы избежать случайного создания пустых элементов, используйте функцию find(), чтобы получить искомый элемент:

  map<int, Film>::const_iterator it = films.find(1817); 
  if (it != films.end()) 
    cerr << "Found " << (*it).second.title().ascii() << endl;
      
Эта функция вернет итератор end(), если ключ отсутствует в словаре.

В примере выше, в качестве ключа использовались целые числа, однако, для этих целей могут использоваться и другие типы. Наиболее популярный -- QString, например:

  map<QString, QString> actorToNationality; 
  actorToNationality["Doris Day"] = "American"; 
  actorToNationality["Greta Garbo"] = "Swedish";
      
Если необходимо хранить несколько значений с одинаковыми ключами, используйте multimap<K, T>. Если необходимо хранить одни только ключи, используйте set<K> или multiset<K>. Qt не имеет классов, эквивалентных приведенным.

Класс QMap<K, T> имеет несколько дополнительных функций, особенно удобных при работе с небольшими наборами данных. Функции QMap<K, T>::keys() и QMap<K, T>::values() возвращают списки QValueList ключей и значений словаря.




Спонсоры:
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2021 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру