Предположим, что мы не уверены, существует ли объект
Hash
, но хотели бы избежать очистки имеющегося хэша. Очевидное решение — проверить, определен ли интересующий нас объект:
unless defined? а
а={}
end
a["flat"] = 3
Но есть и другой способ:
а ||= {}
a["flat"] = 3
#
Или даже так:
(а ||= {})["flat"] = 3
Тот же вопрос можно поставить для отдельных ключей, когда новое значение следует присваивать, лишь если такого ключа еще нет:
a=Hash.new(99)
а[2] # 99
а # {}
а[2] ||= 5 # 99
а # {}
b=Hash.new
b # {}
b[2] # nil
b[2] ||= 5 # 5
b # {2=>5}
Отметим, что nil может выступать и в качестве ключа, и в качестве значения:
b={}
b[2] # nil b[3]=nil
b # {3=>nil}
b[2].nil? # true
b[3].nil? # true b[nil]=5
b # {3=>nil,nil=>5}
b[nil] # 5
b[b[3]] # 5
8.2.4. Удаление пар ключ-значение
Удалить пары ключ-значение из хэша можно с помощью методов
clear
,
delete
,
delete_if
,
reject
,
reject!
и
shift
.
Метод
clear
удаляет из хэша все пары. Эффект такой же, как от присваивания переменной нового пустого хэша, но работает чуть быстрее.
Метод
shift
удаляет незаданную пару ключ-значение и возвращает ее в виде массива из двух элементов или
nil
, если никаких ключей не осталось.
a = {1=>2, 3=>4}
b = a.shift # [1,2]
# а равно {3=>4}
Метод
delete
удаляет конкретную пару ключ-значение. Он принимает в качестве параметра ключ и возвращает ассоциированное с ним значение, если такой ключ существовал (и был удален). В противном случае возвращается значение по умолчанию. Метод также принимает блок, который вырабатывает уникальное значение по умолчанию вместо того, чтобы возвращать ссылку на общий объект.
a = (1=>1, 2=>4, 3=>9, 4=>16)
a.delete(3) # 9
# a is now {1=>1, 2 =>4, 4=>16)
a.delete(5) # в этом случае nil.
delete(6) { "не
найдено" } # "не найдено".
Пользуйтесь методами
delete_if
,
reject
или
reject!
в сочетании с обязательны блоком, чтобы удалить все ключи, для которых блок возвращает значение
true
. Метод
reject
работает с копией хэша, а метод
reject!
возвращает
nil
, если не было произведено никаких изменений.
8.2.5. Обход хэша
В классе
Hash
имеется стандартный итератор
each
, а кроме него итераторы
each_key
,
each_pair
и
each_value
(
each_pair
— синоним
each
).
{"а"=>3, "b"=>2}.each do |key, val|
print val, " из ", key, "; " # 3 из a; 2 из b;
end
Остальные два итератора передают в блок только ключ или только значение:
print "значение = #{value};" # Печатается: значение = 3; val = 2;
end
8.2.6. Инвертирование хэша
Инвертирование хэша осуществляется в Ruby тривиально с помощью метода
invert
:
а = {"fred"=>"555-1122","jane"=>"555-7779"}
b = a.invert
b["555-7779"] # "jane"
Поскольку ключи в хэше уникальны, такая операция может привести к потере данных. Значения-дубликаты будут преобразованы в уникальный ключ, которому соответствует какое-то одно из множества прежних значений. Предсказать, какое именно, невозможно.
8.2.7. Поиск ключей и значений в хэше
Определить, было ли присвоено значение некоторому ключу, позволяет метод
has_key?
или любой из его синонимов
include?
,
key?
,
member?
:
а = {"а"=>1,"b"=>2}
a.has_key? "с" # false
a.include? "а" # true
a.key? 2 # false
a.member? "b" # true
Можно также воспользоваться методом
empty?
, чтобы узнать, остался ли в хэше хотя бы один ключ. А метод