10.8. Ассоциативные массивы

Ассоциативный массив (АМ) - это массив для доступа к элементам которого используются ассоциативные строки. Рассмотрим ассоциативные массивы в сравнении с обычными массивами. Обычный массив выглядит следующим образом:

declare m[5]
m[1]=11; m[2]=12; ....

Ключами доступа к элементам являются непрерывный ряд чисел, ограниченный объявленным размером массива. Вставка в такой массив нового элемента становится проблемой, и это чревато неизбежными издержакми. В отличии от обычных массивов, элементы ассоциативного массива идентифицируются строками. Функция map() создает пустой ассоциативный массив. Новые элементы в ассоциативный массив добавляются автоматически. Для доступа к элементам ассоциативного массива может быть использован стиль объектно ориентированного синтаксиса. Например:

// create an empty associative array
m=map()
// add two elements
m:asdf=11; m:qwer=12
? valtype(m) // 'O' (object)
? len(m)     // 2
? m:qwer     // 12

Если быть точнее, элементы ассоциативного массива идентифицируются хэш-кодами строк. Хэш-код - это число, получаемое путем хэширования строки с использованием битовых операций. Для строк длиной до 20 символов, вероятность совпадения хэш-кодов двух различных строк равна приблизительно 1/1000000. Для более длинных строк, вероятность увеличивается.

Компилятор вычисляет хэш-коды строк заключенных в символы "`". Например:

? m:qwer == m[`qwer`] // .t.

Компилятор также вычисляет хэш-коды строк с префиксом hash_. В этом случае строки не переводятся к верхнему регистру. Вы должны делать это сами:

? m:qwer == m[hash_qwer] // .f.
? m:qwer == m[hash_QWER] // .t.

Во время выполнения хэш-код может быть вычислен при помощи функции hashstr():

? m:qwer == m[hashstr("QWER")] // .t.

Замечание

Обратите внимание что QWER большими буквами, потому что компилятор не чувствителен к регистру символов.

Можно получить список индексов (хэш-кодов элементов) ассоциативного массива при помощи функции mapkeys() которая возвращает обычный массив содержащий хэш-коды всех элементов ассоциативного массива:

mm := mapkeys(m)
? len(mm) // 2
for i to len(mm)
	? mm[i] // something like 1233345677, 124321423
next

Ассоциативный массив характеризуется быстрым доступом к элементам.