Это перевод статьи «Associative arrays», опубликованной 1 января 2016 года. На мой вкус статья несколько излишне поверхностна и не содержит большого количества подробностей, но она может быть полезной тем, кто знаком с ассоциативными массивами в других языках программирования.
В языке D есть встроенная поддержка ассоциативных массивов, также известных как хэш-таблицы.
Они аналогичны
Чтобы объявить ассоциативный массив, используйте следующий синтаксис:
Для вставки элементов в ассоциативный массив используйте оператор
Ниже приведён пример создания ассоциативного массива квадратов целых чисел от 0 до 10 и вывода их на экран.
Запустив пример, мы получим следующий вывод:
Обратите внимание, что числа не отсортированы — это ожидаемо: ассоциативные массивы внутренне не сортируются.
Примечания:
Для удаления элементов из ассоциативного массива используйте функцию
Для проверки ключа на существование используйте оператор
Существует два способа очистить ассоциативный массив:
Чтобы выбросить существующий массив, присвойте ему значение
Мы уже знакомы с некоторыми свойствами ассоциативных массивов, например,
Для более подробной информации (например, чтобы узнать о работе с классами и структурами в ассоциативных массивах) обратитесь к официальной документации на dlang.org.
В языке D есть встроенная поддержка ассоциативных массивов, также известных как хэш-таблицы.
Они аналогичны
Map
в Java или std::unordered_map
в C++.Объявление ассоциативного массива
Чтобы объявить ассоциативный массив, используйте следующий синтаксис:
// Прим. перев.: value — тип значения, key — тип ключа
value[key] myAssociativeArray;
Вставка элементов в ассоциативный массив
Для вставки элементов в ассоциативный массив используйте оператор
[]
.Ниже приведён пример создания ассоциативного массива квадратов целых чисел от 0 до 10 и вывода их на экран.
import std.stdio;
void main()
{
int[int] squares; // Объявление
for (int i = 0; i <= 10; ++i)
squares[i] = i * i; // Вставка в ассоциативный массив
writeln(squares);
}
Запустив пример, мы получим следующий вывод:
[0:0, 6:36, 7:49, 2:4, 3:9, 10:100, 1:1, 8:64, 5:25, 4:16, 9:81]
Обратите внимание, что числа не отсортированы — это ожидаемо: ассоциативные массивы внутренне не сортируются.
Примечания:
- Переназначение существующего ключа заменит значение.
- Попытка обратиться к несуществующему ключу приведёт к ошибке
core.exception.RangeError
.
Удаление элементов из ассоциативного массива
Для удаления элементов из ассоциативного массива используйте функцию
remove()
.aa.remove("hello");
Проверка на существование ключа
Для проверки ключа на существование используйте оператор
in
, который возвращает указатель на значение. Если ключ не существует, указатель будет null
.int[int] squares;
// ...
int* p = 10 in squares;
// Прим. перев.: Не проверяйте на null операторами сравнения, используйте is
if (p !is null)
writeln(*p);
else
writeln("Нет значения.");
Очистка ассоциативного массива
Существует два способа очистить ассоциативный массив:
- Пройтись по ключам и удалить их
- Отбросить старый массив и создать новый
Способ 1: удаляем ключи
foreach (key; aa.keys)
aa.remove(key);
Способ 2: создаём новый массив
Чтобы выбросить существующий массив, присвойте ему значение
null
.aa = null; // помечено для сборки мусора
aa[1] = 1; // записано по новому адресу в памяти
Свойства
Мы уже знакомы с некоторыми свойствами ассоциативных массивов, например,
remove()
или keys
. Ниже приведены остальные:Свойство | Описание |
---|---|
.sizeof |
Возвращает размер ссылки на ассоциативный массив. В 32-битных сборках это 4, а в 64-битных сборках 8. |
.length |
Возвращает количество значений в массиве. В отличие от динамических массивов, это свойство только для чтения. |
.dup |
Создаёт ассоциативный массив того же размера и копирует в него содержимое первого массива. |
.keys |
Возвращает динамический массив, элементы которого являются ключами исходного ассоциативного массива. |
.values |
Возвращает динамический массив, элементы которого являются значениями исходного ассоциативного массива. |
.rehash |
На месте реорганизует массив, оптимизируя поиск по нему. rehash полезен, например, когда в программу подгружается таблица символов, по которой впоследствии нужно производить поиск. Возвращает ссылку на реорганизованный массив. |
.byKey() |
Возвращает диапазон, подходящий для перебора с помощью цикла foreach ключей ассоциативного массива. |
.byValue() |
Возвращает диапазон, подходящий для перебора с помощью цикла foreach значений ассоциативного массива. |
.byKeyValue() |
Возвращает диапазон, подходящий для перебора с помощью цикла foreach пар ключ-значение ассоциативного массива. Возвращаемые пары представляются в виде непрозрачного типа со свойствами .key и .value , позволяющими обращаться соответственно к ключу и значению пары. |
.get(Key key, lazy Value defVal) |
Ищет ключ key . Если он существует, возвращает соответствующее ему значение; если не существует, отрабатывает и возвращает значение по умолчанию defVal . |
Что ещё почитать
Для более подробной информации (например, чтобы узнать о работе с классами и структурами в ассоциативных массивах) обратитесь к официальной документации на dlang.org.
Комментарии (6)
AxisPod
09.01.2016 12:50Если это hash map, то он внутри еще как сортируется, но сортируется он сначала по корзинам, в какую попадет значение, а потом внутри, уже по своей внутренней логике. Несортируемые это когда порядок не меняется, а здесь опять же он меняется.
1vanK
09.01.2016 13:59Хеш-таблица должна внутренне упорядочиваться, иначе обращение к нужному элементу будет непозволительно долгим
merhalak
09.01.2016 15:52Проверка на существование ключа может ли быть такой:
int[int] squares; ... int value = 10 if (value in squares) writeln(squares.get(value)); else writeln("Нет значения.");
Или оно не скомпилируется/чем-либо хуже?9mm
09.01.2016 17:49+1хуже только тем, что поиск значения будет произведён дважды — один раз оператором 'in', затем методом 'get'. А так скомпилируется, чё.
лучше уж так:
if (auto v = value in squares) writeln( v );
ReklatsMasters
Когда я писал парсер торрент-файлов на D, выяснилось, что ключи ассоциативных массивов располагаются в памяти не порядку. Это чертовски мешает, пришлось написать костыль.
9mm
в статье об этом, как раз, написано. Если нужно поддержание отношения '<', то нужно, по старинке, использовать RedBlackTree из std.containers.