Перейти к содержанию

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)

Методы класса

[], new

Методы объекта

[]=, [], ==, 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"]

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[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>

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

Hash#indexes

[править]

hsh.indexes(key, ...)    #-> array

Информация

Методы indexes и indices — абсолютно идентичны, то есть являются именами одного и того же метода

Hash#indices

[править]

hsh.indices(key, ...)    #-> array

Информация

Методы 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 — абсолютно идентичны, то есть являются именами одного и того же метода

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 — абсолютно идентичны, то есть являются именами одного и того же метода

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"]