a.has_value? 2 # true
a.value? 99 # false
8.2.8. Копирование хэша в массив
Чтобы преобразовать весь хэш в массив, пользуйтесь методом to_a
. В получившемся массиве ключи станут элементами с четными индексами (начиная с 0), а значения — с нечетными:
h = {"а"=>1,"b"=>2}
h.to_a # ["а",1,"b",2]
Можно также получить массив, содержащий только ключи или только значения:
h.keys # ["а","b"]
h.values # [1,2]
Наконец, можно поместить в массив только значения, соответствующие заданному списку ключей. Этот метод работает для хэшей примерно так же, как одноименный метод для массивов. (Кроме того, как и в случае массивов, метод values_at
заменяет устаревшие методы indices
и indexes
.)
h = {1=>"one", 2=>"two", 3=>"three", 4=>"four", "cinco"=>"five"}
h.values_at(3,"cinco",4) # ["three","five","four"]
h.values_at(1,3) # ["one","three"]
8.2.9. Выборка пар ключ-значение по заданному критерию
К классу Hash
подмешан модуль Enumerable
, поэтому можно обращаться к методам detect
( find
), select
( find_all
), grep
, min
, max
и reject
(как и для массивов).
Метод detect
(синоним find
) находит одну пару ключ-значение. Он принимает блок (которому передается по одной паре за раз) и возвращает первую пару, для которой вычисление блока дает true
.
names = {"fred"=>"jones","jane"=>"tucker", "joe"=>"tucker","mary"=>"SMITH"}
# Найти tucker.
names.detect {|k,v| v=="tucker" } # ["joe","tucker"]
# Найти имена, записанные прописными буквами.
names.find {|k,v| v==v.upcase } # ["mary", "SMITH"]
Разумеется, объекты в хэше могут быть сколь угодно сложными, как и условие, проверяемое в блоке, но сравнение объектов разных типов может оказаться проблематичным.
Метод select
(синоним find_all
) возвращает все пары, удовлетворяющие условию, а не только первую:
names.select {|k,v| v=="tucker" }
# [["joe", "tucker"], ["jane", "tucker"]]
names.find_all (|k,v| k.count("r")>0}
# [["mary", "SMITH"], ["fred", "jones"]]
Хэши по природе своей не упорядочены ни по ключам, ни по значениям. Чтобы отсортировать хэш, Ruby преобразует его в массив, который затем сортирует. Понятно, что и результатом является массив.
names = {"Jack"=>"Ruby","Monty"=>"Python",
"Blaise"=>"Pascal", "Minnie"=>"Perl"} list = names.sort
# list равно:
# [["Blaise","Pascal"], ["Jack","Ruby"],
# ["Minnie","Perl"], ["Monty","Python"]]
8.2.11. Объединение двух хэшей
Иногда бывает нужно объединить хэши. Метод merge
получает два хэша и формирует из них третий, перезаписывая обнаружившиеся дубликаты:
dict = {"base"=>"foundation", "pedestal"=>"base"}
added = {"base"=>"non-acid", "salt"=>"NaCl"}
new_dict = diet.merge(added)
# {"base" =>"non-acid", "pedestal" =>"base", "salt"=>"NaCl"}
У метода merge
есть синоним update
.
Если задан блок, то он может содержать алгоритм устранения коллизий. В нижеприведенном примере, если два ключа совпадают, в объединенном хэше остается меньшее значение (по алфавиту, по числовому значению или в каком-то ином смысле):
dict = {"base"=>"foundation", "pedestal"=>"base"}
added = {"base"=>"non-acid", "salt" =>"NaCl"}
new_dict = diet.merge(added) {|key,old,new| old < new ? old : new }
# {"salt"=>"NaCl", "pedestal"=>"base", "base"=>"foundation"}
Таким образом, при использовании блока результат может получиться не такой, как в случае, когда блок не задан. Имеются также методы merge!
и update!
, которые изменяют вызывающий объект «на месте».
8.2.12. Создание хэша из массива
Простейший способ сделать это — прибегнуть к способу создания хэшей с помощью квадратных скобок. Следующий способ годится, если массив состоит из четного числа элементов.
Array =[2,3,4,5,6,7]
hash = Hash[*array]
# hash равно: {2=>3, 4=>5, 6=>7}
8.2.13. Вычисление разности и пересечения хэшей
Ключи хэша можно скопировать в отдельный массив, а к получившимся из разных хэшей массивам применить методы &
и -
класса Array
. Результатом являются пересечение и разность множеств ключей. Соответствующие им значения можно получить с помощью метода each
, примененного к хэшу, содержащему все образованные таким способом ключи.
а = {"а"=>1,"b"=>2,"z"=>3}
b = {"x"=>99,"у"=>88,"z"=>77}
intersection = a.keys & b.keys
difference = a.keys - b.keys
с = a.dup.update(b)
inter = {}
intersection.each {|k| inter[k]=c[k] }
# inter равно {"z"=>77}
diff={}
difference.each {|k| diff[k]=c[k] }
# diff равно {"а"=>1, "b"=>2}
8.2.14. Хэш как разреженная матрица
Читать дальше
Конец ознакомительного отрывка
Купить книгу