Ruby/Справочник/Hash
Класс Hash
[править]Хеш - коллекция пар ключ-значение. Хеш подобен классу Array, за исключением того, что индексация осуществляется через ключи (объекты любого типа), а не через целочисленные индексы. Последовательность перечисления пар ключ-значений хеша может оказаться произвольной, и обычно не совпадает с той, в которой вы заполняли хеш. При обращении к хешу по ключу, которого не существует, возвращается значение по-умолчанию. Изначально, этим значением является nil.
Примеси
Enumerable (all?, any?, collect, detect, each_cons, each_slice, each_with_index, entries, enum_cons, enum_slice, enum_with_index, find, find_all, grep, group_by, include?, index_by, inject, map, max, member?, min, partition, reject, select, sort, sort_by, sum, to_a, to_set, zip)
Методы класса
Методы объекта
[]=, [], ==, clear, default=, default_proc, default, delete_if, delete, each_key, each_pair, each_value, each, empty?, fetch, has_key?, has_value?, include?, indexes, index, indices, inspect, invert, key?, keys, length, member?, merge!, merge, rehash, reject!, reject, replace, select, shift, size, sort, store, to_a, to_hash, to_s, update, value?, values_at, values
Hash::[]
[править]Hash [key =>|, value]* ] #-> hash
Создает новый хеш, заполненный заданными объектами. Эквивалентно литералу { key, value, ... }.
Hash["a", 100, "b", 200] #-> {"a"=>100, "b"=>200}
Hash["a" => 100, "b" => 200] #-> {"a"=>100, "b"=>200}
{ "a" => 100, "b" => 200 } #-> {"a"=>100, "b"=>200}
Внимание! Ключи и значения состоят в парах, поэтому требуется четное число аргументов |
Hash::new
[править]Hash.new #-> hash
Hash.new(obj) #-> aHash
Hash.new {|hash, key| block } #-> aHash
Возвращает новый хеш. При последующем обращении к хешу по ключу, которого не существует в этом хеше, возвращаемое значение зависит от формы вызова метода new. В первой форме вызова вернется значение nil. Если указан объект obj, то этот единственный объект будет использоваться для всех значений по-умолчанию. Если указан блок, тогда значение по-умолчанию вычисляется в данном блоке, которому передаются хеш (текущий) и ключ. В блоке можно записать значение в хеш, если это необходимо.
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #-> 100
h["c"] #-> "Go Fish"
# Изменяется единственный объект по-умолчанию
h["c"].upcase! #-> "GO FISH"
h["d"] #-> "GO FISH"
h.keys #-> ["a", "b"]
# Создается новый объект по умолчанию каждый раз
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #-> "Go Fish: c"
h["c"].upcase! #-> "GO FISH: C"
h["d"] #-> "Go Fish: d"
h.keys #-> ["c", "d"]
Hash#==
[править]hsh == other_hash #-> true или false
Равенство — два хеша считаются равными, если они содержат одинаковое число ключей, и если каждая пара ключ-значение эквивалентна (согласно методу Object#==) соответствующим элементам в другом хеше.
h1 = { "a" => 1, "c" => 2 }
h2 = { 7 => 35, "c" => 2, "a" => 1 }
h3 = { "a" => 1, "c" => 2, 7 => 35 }
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h1 == h2 #-> false
h2 == h3 #-> true
h3 == h4 #-> false
Hash#[]
[править]hash[key] #-> value
Получение элемента — возвращает значение соответствующее ключу key. Если ключа не существует, то возвращается значение по-умолчанию (см. Hash::new).
h = { "a" => 100, "b" => 200 }
h["a"] #-> 100
h["c"] #-> nil
Hash#[]=
[править]hsh[key] = value #-> value
Присваивание - ассоциирует значение value с ключем key.
h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h #-> {"a"=>9, "b"=>200, "c"=>4}
Данный метод и метод store — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#clear
[править]hsh.clear #-> hsh
Удаляет все пары ключ-значение из хеша hsh.
h = { "a" => 100, "b" => 200 } #-> {"a"=>100, "b"=>200}
h.clear #-> {}
Hash#default
[править]hsh.default(key=nil) #-> obj
Возвращает значение по-умолчанию, т.е. значение, которое будет возвращать hsh[key], если ключа key не существует в хеше hsh.
h = Hash.new #-> {}
h.default #-> nil
h.default(2) #-> nil
h = Hash.new("cat") #-> {}
h.default #-> "cat"
h.default(2) #-> "cat"
h = Hash.new {|h,k| h[k] = k.to_i*10} #-> {}
h.default #-> 0
h.default(2) #-> 20
Полезно взглянуть также на методы Hash::new и Hash#default= |
Hash#default=
[править]hsh.default = obj #-> hsh
Устанавливает значение по-умолчанию, т.е. значение, которое возвращает hsh[key], если ключа key не существует в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.default = "Go fish"
h["a"] #-> 100
h["z"] #-> "Go fish"
# Это не сделает того, на что вы надеятесь...
h.default = proc do |hash, key|
hash[key] = key + key
end
h[2] #-> #<Proc:0x401b3948@-:6>
h["cat"] #-> #<Proc:0x401b3948@-:6>
Внимание! Таким способом в качестве значения по-умолчанию нельзя установить Proc, который будет выполняться при каждом обращении по ключу |
Hash#default_proc
[править]hsh.default_proc #-> anObject
Если метод Hash::new был вызван с блоком, то возвращает блок, иначе возвращает nil.
h = Hash.new {|h,k| h[k] = k*k } #-> {}
p = h.default_proc #-> #<Proc:0x401b3d08@-:1>
a = [] #-> []
p.call(a, 2)
a #-> [nil, nil, 4]
Hash#delete
[править]hsh.delete(key) #-> value
hsh.delete(key) {| key | block } #-> value
Удаляет пару ключ-значение из хеша hsh, которая соответствует ключу key. Возвращается значение, соответствующее ключу. Если ключ не был найден, тогда возвращается "значение по-умолчанию". Если используется конструкция с блоком и ключ не был найден, то возвращается результат выполнения блока block, которому передается ключ key.
h = { "a" => 100, "b" => 200 }
h.delete("a") #-> 100
h.delete("z") #-> nil
h.delete("z") { |el| "#{el} не найден" } #-> "z не найден"
Hash#delete_if
[править]hsh.delete_if {| key, value | block } #-> hsh
Удаляет все пары ключ-значение из хеша hsh для которых блок block вычисляет значение true.
h = { "a" => 100, "b" => 200, "c" => 300 }
h.delete_if {|key, value| key >= "b" } #-> {"a"=>100}
Hash#each
[править]hsh.each {| key, value | block } #-> hsh
Вызывает блок для каждый пары ключ-значение хеша hsh и передает в блок текущую пару ключ-значение в виде массива из двух элементов. В виду семантических особенностей параметров блока, эти параметры могут быть представлены не массивом, а двумя элементами с различными именами. Еще существует метод each_pair, который чуть более эффективен для блоков с двумя параметрами.
h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} => #{value}" }
результат:
a => 100 b => 200
Hash#each_key
[править]hsh.each_key {| key | block } #-> hsh
Выполняет блок block для каждого ключа в хеше hsh, передавая в блок ключ key в качестве параметра.
h = { "a" => 100, "b" => 200 }
h.each_key {|key| puts key }
результат:
a b
Hash#each_pair
[править]hsh.each_pair {| key_value_array | block } #-> hsh
Выполняет блок block для каждого ключа в хеше hsh, передавая в блок ключ и значение в качестве параметров.
h = { "a" => 100, "b" => 200 }
h.each_pair {|key, value| puts "#{key} => #{value}" }
результат:
a => 100 b => 200
Hash#each_value
[править]hsh.each_value {| value | block } #-> hsh
Выполняет блок block для каждого ключа в хеше hsh, передавая в блок значение value, соответствующее ключу, в качестве параметра.
h = { "a" => 100, "b" => 200 }
h.each_value {|value| puts value }
результат:
100 200
Hash#empty?
[править]hsh.empty? #-> true или false
Возвращает true, если хеш hsh не содержит пар ключ-значение вовсе.
{}.empty? #-> true
Hash#fetch
[править]hsh.fetch(key [, default] ) #-> obj
hsh.fetch(key) {| key | block } #-> obj
Возвращает значение, соответствующее ключу key. Если ключ не был найден, тогда есть несколько ситуаций: Без иных аргументов будет подниматься исключение IndexError; Если задан параметр default, тогда он и будет возвращен; Если конструкция определена с блоком, тогда будет выполняться блок, которому в качестве аргумента будет передан ключ.
h = { "a" => 100, "b" => 200 }
h.fetch("a") #-> 100
h.fetch("z", "go fish") #-> "go fish"
h.fetch("z") { |el| "go fish, #{el}"} #-> "go fish, z"
Следующий пример показывает, что если ключ не найден и значение по-умолчанию не поставляется, то поднимается исключение.
h = { "a" => 100, "b" => 200 }
h.fetch("z")
результат:
prog.rb:2:in `fetch': key not found (IndexError) from prog.rb:2
Hash#has_key?
[править]hsh.has_key?(key) #-> true или false
Возвращает true, если заданный ключ находится в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.has_key?("a") #-> true
h.has_key?("z") #-> false
Методы has_key?, include?, key? и member? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#has_value?
[править]hsh.has_value?(value) #-> true или false
Возвращает true, если заданное значение принадлежит некоторому ключу в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.has_value?(100) #-> true
h.has_value?(999) #-> false
Методы has_value? и value? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#include?
[править]hsh.include?(key) #-> true или false
Возвращает true, если заданный ключ находится в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.include?("a") #-> true
h.include?("z") #-> false
Методы include?, has_key?, key? и member? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#index
[править]hsh.index(value) #-> key
Возвращает ключ для заданного значения. Если значение не найдено, возвращает nil.
h = { "a" => 100, "b" => 200 }
h.index(200) #-> "b"
h.index(999) #-> nil
Внимание! Использование данного метода резко осуждается Руби-сообществом. Во время его использования интерпретатор будет выдавать предупреждение. Рекомендуется использовать метод key. |
Hash#indexes
[править]hsh.indexes(key, ...) #-> array
Внимание! Данный метод является «устаревшим» и его использование осуждается разработчиками. В следующих версиях языка он будет удален и ваша программа перестанет работать. Используйте метод select, который имеет схожий функционал, но не является «устаревшим» |
Методы indexes и indices — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#indices
[править]hsh.indices(key, ...) #-> array
Внимание! Данный метод является «устаревшим» и его использование осуждается разработчиками. В следующих версиях языка он будет удален и ваша программа перестанет работать. Используйте метод select, который имеет схожий функционал, но не является «устаревшим» |
Методы indices и indexes — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#inspect
[править]hsh.inspect #-> string
Возвращает содержимое хеша в виде строки.
Hash#invert
[править]hsh.invert #-> aHash
Возвращает новый хеш, созданный путем использования значений хеша hsh в качестве ключей, а ключей в качестве значений.
h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert #-> {0=>"a", 100=>"n", 200=>"d", 300=>"y"}
Hash#key
[править]hsh.key(value) #-> key
Возвращает ключ для заданного значения. Если значение не найдено, возвращает nil.
h = { "a" => 100, "b" => 200 }
h.key(200) #-> "b"
h.key(999) #-> nil
Методы index и key — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#key?
[править]hsh.key?(key) #-> true или false
Возвращает true, если заданный ключ находится в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.key?("a") #-> true
h.key?("z") #-> false
Методы key?, has_key?, include? и member? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#keys
[править]hsh.keys #-> array
Возвращает новый массив, состоящий из ключей данного хеша.
h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
h.keys #-> ["a", "b", "c", "d"]
Полезно посмотреть на метод values, который имеет схожую функциональность |
Hash#length
[править]hsh.length #-> fixnum
Возвращает количество пар ключ-значение в данном хеше.
h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.length #-> 4
h.delete("a") #-> 200
h.length #-> 3
Методы length и size — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#member?
[править]hsh.member?(key) #-> true или false
Возвращает true, если заданный ключ находится в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.member?("a") #-> true
h.member?("z") #-> false
Методы member?, has_key?, include? и key? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#merge
[править]hsh.merge(other_hash) #-> a_hash
hsh.merge(other_hash){|key, oldval, newval| block} #-> a_hash
Возвращает новый хеш, который состоит из содержимого хешей other_hash и hsh. Если в результате слияния обнаружатся одинаковые ключи, то для него будет записано значение из хеша other_hash (если задан блок, то будет записано значение, которое получится в результате выполнения блока).
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1 #=> {"a"=>100, "b"=>200}
Hash#merge!
[править]hsh.merge!(other_hash) #-> hsh
hsh.update(other_hash) #-> hsh
hsh.merge!(other_hash){|key, oldval, newval| block} #-> hsh
hsh.update(other_hash){|key, oldval, newval| block} #-> hsh
Добавляет содержимое хеша other_hash к хешу hsh. Если обнаружатся дублирующие ключи, то значение для него будет взято из other_hash (или получено в результате выполнения блока, если он задан).
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
Методы merge! и update — абсолютно идентичны, то есть являются именами одного и того же метода |
Внимание! Данный метод является «опасным», так как изменяет исходный объект. Вместо него рекомендуется использовать метод merge, который не имеет данного побочного эффекта |
Hash#rehash
[править]hsh.rehash #-> hsh
Если ключами хеша являются переменные, то может возникнуть ситуация, когда их значение меняется. Чтобы иметь доступ к ассоциированным с ними данным нужно вызвать данный метод, чтобы он привел ключи в соответствие с новым значеним переменных. Если метод вызывается, в то время как итератор обходит этот самый хеш, то будет возбуждена ошибка вида IndexError.
a = [ "a", "b" ]
c = [ "c", "d" ]
h = { a => 100, c => 300 }
h[a] #-> 100
a[0] = "z"
h[a] #-> nil
h.rehash #-> {["z", "b"]=>100, ["c", "d"]=>300}
h[a] #-> 100
Hash#reject
[править]hsh.reject {| key, value | block } #-> a_hash
То же самое, что и метод delete_if, но обрабатывает (и возвращает) копию хеша hsh. По сути, данный метод эквивалентен hsh.dup.delete_if.
Hash#reject!
[править]hsh.reject! {| key, value | block } #-> hsh или nil
Эквивалентно delete_if, но возвращает nil, если хеш не был изменен в результате работы данного метода.
Hash#replace
[править]hsh.replace(other_hash) #-> hsh
Заменяет содержимое хеша hsh на содержимое хеша other_hash.
h = { "a" => 100, "b" => 200 }
h.replace({ "c" => 300, "d" => 400 }) #-> {"c"=>300, "d"=>400}
Hash#select
[править]hsh.select {|key, value| block} #-> hash
Возвращает новый хэш, состоящий из элементов, для которых блок вычисляет значение true.
h = { "a" => 100, "b" => 200, "c" => 300 }
h.select {|k,v| v > 100} #-> {"b" => 200, "c" => 300}
h.select {|k,v| v < 200} #-> {"a" => 100}
А вот так выбираем только гласные:
hash_1 = {a: 1, e: 5, i: 9, o: 15, u: 21, y: 25, b: 2, c: 3, d: 4, f: 6, g: 7, h: 8, j: 10, k: 11, l: 12, m: 13, n: 14, p: 16, q: 17, r: 18, s: 19, t: 20, v: 22, w: 23, x: 24, z: 26}
hash_2 = hash_1.select! { |k, v| [:a, :e, :i, :o, :u, :y].include?(k) }
p hash_2
На выходе {:a=>1, :e=>5, :i=>9, :o=>15, :u=>21, :y=>25}
Осторожно с ! после select ...
Hash#shift
[править]hsh.shift #-> anArray или obj
Удаляет первую пару ключ-значение из хеша hsh и возвращает эту пару в виде массива [ key, value ]. Если хеш пуст, то возвращает значение по-умолчанию.
h = { 1 => "a", 2 => "b", 3 => "c" }
h.shift #-> [1, "a"]
h #-> {2=>"b", 3=>"c"}
Hash#size
[править]hsh.size #-> fixnum
Возвращает количество пар ключ-значение в данном хеше.
h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.size #-> 4
h.delete("a") #-> 200
h.size #-> 3
Методы size и length — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#sort
[править]hsh.sort #-> array
hsh.sort {| a, b | block } #-> array
Преобразует хеш hsh в массив массивов - [ key, value ] и сортирует его, используя Array#sort.
h = { "a" => 20, "b" => 30, "c" => 10 }
h.sort #-> [["a", 20], ["b", 30], ["c", 10]]
h.sort {|a,b| a[1]<=>b[1]} #-> [["c", 10], ["a", 20], ["b", 30]]
Hash#store
[править]hsh.store(key, value) #-> value
Присваивание - ассоциирует значение value с ключем key. Идентичен методу []=.
h = { "a" => 100, "b" => 200 }
h.store("a", 9)
h.store("c", 4)
h #-> {"a"=>9, "b"=>200, "c"=>4}
Hash#to_a
[править]hsh.to_a #-> array
Конвертирует хеш hsh в массив, состоящий из массивов [ key, value ].
h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
h.to_a #-> [["a", 100], ["c", 300], ["d", 400]]
Hash#to_hash
[править]hsh.to_hash #-> hsh
Возвращает hsh.
Hash#to_s
[править]hsh.to_s #-> string
Преобразует хеш hsh в строку путем преобразования хеша в массив массивов [ key, value ], и преобразования этого массива в строку, используя Array#join со стандартным разделителем.
h = { "c" => 300, "a" => 100, "d" => 400 }
h.to_s #-> "a100c300d400"
Hash#update
[править]hsh.merge!(other_hash) #-> hsh
hsh.update(other_hash) #-> hsh
hsh.merge!(other_hash){|key, oldval, newval| block} #-> hsh
hsh.update(other_hash){|key, oldval, newval| block} #-> hsh
Добавляет содержимое хеша other_hash к хешу hsh. Если обнаружатся дублирующие ключи, то значение для него будет взято из other_hash (или получено в результате выполнения блока, если он задан).
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.update(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
Методы merge! и update — абсолютно идентичны, то есть являются именами одного и того же метода |
Внимание! Данный метод является «опасным», так как изменяет исходный объект. Вместо него рекомендуется использовать метод merge, который не имеет данного побочного эффекта |
Hash#value?
[править]hsh.value?(value) #-> true или false
Возвращает true, если заданное значение принадлежит некоторому ключу в хеше hsh.
h = { "a" => 100, "b" => 200 }
h.value?(100) #-> true
h.value?(999) #-> false
Методы value? и has_value? — абсолютно идентичны, то есть являются именами одного и того же метода |
Hash#values
[править]hsh.values #-> array
Возвращает новый массив, состоящий из значений данного хеша.
h = { "a" => 100, "b" => 200, "c" => 300 }
h.values #=> [100, 200, 300]
Полезно посмотреть на метод keys, который имеет схожую функциональность |
Hash#values_at
[править]hsh.values_at(key, ...) #-> array
Возвращает массив содержащий значения, соответствующие заданным ключам. (См. Hash.select).
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
h.values_at("cow", "cat") #-> ["bovine", "feline"]