Spec-Zone.ru › Ruby 4.0

класс Hash

Родительский класс:
Object
Подключенные модули:
Enumerable

Объект Hash сопоставляет каждому из своих уникальных ключей определённое значение.

У хеша есть некоторые сходства с Array, но:

  • Индекс массива всегда является целым числом.

  • Ключом хеша может быть (почти) любой объект.

Синтаксис данных хеша

В исходном синтаксисе для записи хеша используется «стрелка хеша» =>:

h = {:foo => 0, :bar => 1, :baz => 2}
h # => {foo: 0, bar: 1, baz: 2}

Кроме того, но только для ключа-символа, можно использовать более новый синтаксис в стиле JSON, в котором каждое непомеченное слово становится символом:

h = {foo: 0, bar: 1, baz: 2}
h # => {foo: 0, bar: 1, baz: 2}

Вместо непомеченного слова также можно использовать строку:

h = {'foo': 0, 'bar': 1, 'baz': 2}
h # => {foo: 0, bar: 1, baz: 2}

Можно также сочетать эти стили:

h = {foo: 0, :bar => 1, 'baz': 2}
h # => {foo: 0, bar: 1, baz: 2}

Но попытка использовать синтаксис в стиле JSON для ключа, который не является непомеченным словом или строкой, приведёт к ошибке:

# Raises SyntaxError (syntax error, unexpected ':', expecting =>):
h = {0: 'zero'}

Значение можно опустить; в этом случае оно будет получено из контекста по имени ключа:

x = 0
y = 100
h = {x:, y:}
h # => {x: 0, y: 100}

Распространённые способы использования

Можно использовать хеш, чтобы присвоить объектам имена:

person = {name: 'Matz', language: 'Ruby'}
person # => {name: "Matz", language: "Ruby"}

Можно использовать хеш, чтобы задать имена аргументам метода:

def some_method(hash)
  p hash
end
some_method({foo: 0, bar: 1, baz: 2}) # => {foo: 0, bar: 1, baz: 2}

Примечание: если последний аргумент в вызове метода — хеш, фигурные скобки можно опустить:

some_method(foo: 0, bar: 1, baz: 2) # => {foo: 0, bar: 1, baz: 2}

Можно использовать хеш для инициализации объекта:

class Dev
  attr_accessor :name, :language
  def initialize(hash)
    self.name = hash[:name]
    self.language = hash[:language]
  end
end
matz = Dev.new(name: 'Matz', language: 'Ruby')
matz # => #<Dev: @name="Matz", @language="Ruby">

Создание хеша

Можно явно создать объект Hash с помощью:

  • литерала хеша.

Некоторые объекты можно преобразовать в хеши с помощью:

  • Метода Kernel#Hash.

Можно создать хеш, вызвав метод Hash.new:

# Create an empty hash.
h = Hash.new
h # => {}
h.class # => Hash

Можно создать хеш, вызвав метод Hash.[]:

# Create an empty hash.
h = Hash[]
h # => {}
# Create a hash with initial entries.
h = Hash[foo: 0, bar: 1, baz: 2]
h # => {foo: 0, bar: 1, baz: 2}

Можно создать хеш, используя его литеральную форму (фигурные скобки):

# Create an empty hash.
h = {}
h # => {}
# Create a +Hash+ with initial entries.
h = {foo: 0, bar: 1, baz: 2}
h # => {foo: 0, bar: 1, baz: 2}

Основы значений хеша

Самый простой способ получить значение хеша (метод экземпляра []):

h = {foo: 0, bar: 1, baz: 2}
h[:foo] # => 0

Самый простой способ создать или обновить значение хеша (метод экземпляра []=):

h = {foo: 0, bar: 1, baz: 2}
h[:bat] = 3 # => 3
h # => {foo: 0, bar: 1, baz: 2, bat: 3}
h[:foo] = 4 # => 4
h # => {foo: 4, bar: 1, baz: 2, bat: 3}

Самый простой способ удалить запись хеша (метод экземпляра delete):

h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {foo: 0, baz: 2}

Порядок записей

Объект Hash возвращает свои записи в порядке их создания. Это проявляется в:

  • Итеративных методах, таких как each, each_key, each_pair, each_value.

  • Других методах, чувствительных к порядку, таких как shift, keys, values.

  • Строке, возвращаемой методом inspect.

Начальный порядок записей нового хеша определяется заданными записями:

h = Hash[foo: 0, bar: 1]
h # => {foo: 0, bar: 1}

Новые записи добавляются в конец:

h[:baz] = 2
h # => {foo: 0, bar: 1, baz: 2}

Обновление значения не влияет на порядок:

h[:baz] = 3
h # => {foo: 0, bar: 1, baz: 3}

Но повторное создание удалённой записи может повлиять на порядок:

h.delete(:foo)
h[:foo] = 5
h # => {bar: 1, baz: 3, foo: 5}

Hash Ключи

Hash Эквивалентность ключей

Два объекта считаются одинаковым ключом хеша, если их значения hash идентичны и эти два объекта eql? друг другу.

Изменение активного Hash ключа

Изменение ключа Hash, пока он используется, повреждает индекс хеша.

У этого Hash в качестве ключей используются массивы:

a0 = [ :foo, :bar ]
a1 = [ :baz, :bat ]
h = {a0 => 0, a1 => 1}
h.include?(a0) # => true
h[a0] # => 0
a0.hash # => 110002110

Изменение элемента массива a0[0] изменяет его хеш-значение:

a0[0] = :bam
a0.hash # => 1069447059

И повреждает индекс Hash:

h.include?(a0) # => false
h[a0] # => nil

Можно восстановить индекс хеша с помощью метода rehash:

h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
h.include?(a0) # => true
h[a0] # => 0

Ключ типа String всегда безопасен. Это связано с тем, что незамороженный объект String, переданный в качестве ключа, будет заменён дублированной замороженной строкой:

s = 'foo'
s.frozen? # => false
h = {s => 0}
first_key = h.keys.first
first_key.frozen? # => true

Определяемые пользователем ключи Hash

Чтобы использовать объекты в качестве ключа Hash, они должны реализовать методы hash и eql?. Примечание: это требование не применяется, если в Hash используется compare_by_identity, поскольку сравнение тогда будет опираться на идентификатор объекта ключа, а не на hash и eql?.

Object определяет базовую реализацию для hash и eq?, благодаря которой каждый объект является отдельным ключом. Обычно в классах, определяемых пользователем, эти методы переопределяют, чтобы задать осмысленное поведение, или, например, наследуются от Struct, где уже есть полезные определения этих методов.

Типичная реализация hash основана на данных объекта, а eql? обычно задаётся как псевдоним переопределённого метода ==:

class Book
  attr_reader :author, :title

  def initialize(author, title)
    @author = author
    @title = title
  end

  def ==(other)
    self.class === other &&
      other.author == @author &&
      other.title == @title
  end

  alias eql? ==

  def hash
    [self.class, @author, @title].hash
  end
end

book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'

reviews = {}

reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'

reviews.length #=> 1

Ключ не найден?

Когда метод пытается получить и вернуть значение по ключу и этот ключ найден, возвращаемым значением будет значение, связанное с ключом.

Но что, если ключ не найден? В этом случае одни методы вернут значение по умолчанию, а другие вызовут исключение KeyError.

Возвращаемое значение nil

Если для ненайденного ключа нужно вернуть nil, можно вызвать:

  • [](key) (обычно записывается как #[key].

  • assoc(key).

  • dig(key, *identifiers).

  • values_at(*keys).

Это поведение можно переопределить для методов [], dig и values_at (но не для assoc); см. раздел Значение хеша по умолчанию.

KeyError

Если для ненайденного ключа нужно вызвать исключение KeyError, можно вызвать:

  • fetch(key).

  • fetch_values(*keys).

Значение хеша по умолчанию

Для некоторых методов ([], dig и values_at) возвращаемое значение для ненайденного ключа определяется двумя свойствами хеша:

  • значение по умолчанию: возвращается методом default.

  • процедура по умолчанию: возвращается методом default_proc.

В простом случае оба значения равны nil, и методы возвращают nil для ненайденного ключа; см. раздел «Возвращаемое значение nil» выше.

Обратите внимание, что этот раздел целиком («Значение хеша по умолчанию»):

  • Применяется только к методам [], dig и values_at.

  • Не применяется к методам assoc, fetch или fetch_values, на которые не влияют ни значение по умолчанию, ни процедура по умолчанию.

Значение по умолчанию для любого ключа

Для хеша можно определить значение по умолчанию для любого ключа, то есть значение, которое будет возвращаться для любого ненайденного ключа:

  • Значение default_proc должно быть nil.

  • Значение default (которым может быть любой объект, в том числе nil) будет возвращаться для ненайденного ключа.

Значение по умолчанию можно задать при создании хеша с помощью Hash.new и параметра default_value либо позже с помощью метода default=.

Примечание: хотя значением default может быть любой объект, использовать изменяемый объект может быть не лучшей идеей.

Значения по умолчанию для отдельных ключей

Для хеша можно определить значение по умолчанию для каждого ключа отдельно, то есть Proc, которая будет возвращать значение на основе самого ключа.

Процедуру по умолчанию можно задать при создании хеша с помощью Hash.new и блока либо позже с помощью метода default_proc=.

Обратите внимание, что процедура может изменять self, но такое изменение self небезопасно при работе с потоками: несколько потоков могут одновременно вызвать процедуру по умолчанию для одного и того же ключа.

Значение по умолчанию для метода

Для двух методов можно задать значение для ненайденного ключа, которое будет действовать только в рамках одного вызова метода (и не повлияет на последующие вызовы):

  • Для метода fetch можно задать значение по умолчанию для любого ключа:

  • Для метода fetch или метода fetch_values можно задать значение по умолчанию для отдельного ключа с помощью блока.

Что здесь есть

Сначала рассмотрим то, что находится в других местах. Класс Hash:

  • Наследуется от класса Object.

  • Подключает модуль Enumerable, предоставляющий десятки дополнительных методов.

Здесь класс Hash предоставляет методы, полезные для:

  • создания хеша

  • задания состояния хеша

  • проверки

  • сравнения

  • получения значений

  • присваивания

  • удаления

  • перебора

  • преобразования

  • преобразования ключей и значений

Класс Hash также включает методы из модуля Enumerable.

Методы создания Hash

  • ::[]: возвращает новый хеш, заполненный заданными объектами.

  • ::new: возвращает новый пустой хеш.

  • ::try_convert: возвращает новый хеш, созданный из заданного объекта.

Методы задания состояния Hash

  • compare_by_identity: задаёт для self сравнение ключей только по идентичности.

  • default=: задаёт указанное значение по умолчанию.

  • default_proc=: задаёт указанную процедуру по умолчанию.

  • rehash: перестраивает хеш-таблицу, заново вычисляя индекс хеша для каждого ключа.

Методы проверки

  • any?: возвращает, удовлетворяет ли какой-либо элемент заданному критерию.

  • compare_by_identity?: возвращает, сравнивает ли хеш ключи только по идентичности.

  • default: возвращает значение по умолчанию или значение по умолчанию для заданного ключа.

  • default_proc: возвращает процедуру по умолчанию.

  • empty?: возвращает, нет ли в хеше записей.

  • eql?: возвращает, равен ли заданный объект self.

  • hash: возвращает целочисленный хеш-код.

  • has_value? (псевдоним value?): возвращает, является ли заданный объект значением в self.

  • include? (псевдонимы has_key?, member?, key?): возвращает, является ли заданный объект ключом в self.

  • size (псевдоним length): возвращает количество записей.

Методы сравнения

  • <: возвращает, является ли self собственным подмножеством заданного объекта.

  • <=: возвращает, является ли self подмножеством заданного объекта.

  • ==: возвращает, равен ли заданный объект self.

  • >: возвращает, является ли self собственным надмножеством заданного объекта

  • >=: возвращает, является ли self надмножеством заданного объекта.

Методы получения значений

  • []: возвращает значение, связанное с заданным ключом.

  • assoc: возвращает массив из двух элементов, содержащий заданный ключ и его значение.

  • dig: возвращает объект во вложенных объектах, указанный заданным ключом и дополнительными аргументами.

  • fetch: возвращает значение для заданного ключа.

  • fetch_values: возвращает массив со значениями, связанными с заданными ключами.

  • key: возвращает ключ первой найденной записи с заданным значением.

  • keys: возвращает массив со всеми ключами из self.

  • rassoc: возвращает массив из двух элементов, состоящий из ключа и значения первой найденной записи с заданным значением.

  • values: возвращает массив со всеми значениями из self.

  • values_at: возвращает массив со значениями для заданных ключей.

Методы присваивания

  • []= (псевдоним store): связывает заданный ключ с заданным значением.

  • merge: возвращает хеш, полученный объединением каждого заданного хеша с копией self.

  • update (псевдоним merge!): объединяет каждый заданный хеш с self.

  • replace (псевдоним initialize_copy): заменяет всё содержимое self содержимым заданного хеша.

Методы удаления

Эти методы удаляют записи из self:

  • clear: удаляет все записи из self.

  • compact!: удаляет из self все записи со значением nil.

  • delete: удаляет запись для заданного ключа.

  • delete_if: удаляет записи, выбранные заданным блоком.

  • select! (псевдоним filter!): оставляет только записи, выбранные заданным блоком.

  • keep_if: оставляет только записи, выбранные заданным блоком.

  • reject!: удаляет записи, выбранные заданным блоком.

  • shift: удаляет и возвращает первую запись.

Эти методы возвращают копию self, из которой удалены некоторые записи:

  • compact: возвращает копию self, из которой удалены все записи со значением nil.

  • except: возвращает копию self, из которой удалены записи для указанных ключей.

  • select (псевдоним filter): возвращает копию self, содержащую только записи, выбранные заданным блоком.

  • reject: возвращает копию self, из которой удалены записи, указанные заданным блоком.

  • slice: возвращает хеш, содержащий записи для заданных ключей.

Методы перебора

  • each_pair (псевдоним each): вызывает заданный блок для каждой пары «ключ-значение».

  • each_key: вызывает заданный блок для каждого ключа.

  • each_value: вызывает заданный блок для каждого значения.

Методы преобразования

  • flatten: возвращает массив, представляющий собой одномерное уплощение self.

  • inspect (псевдоним to_s): возвращает новую String, содержащую записи хеша.

  • to_a: возвращает новый массив из массивов по два элемента; каждый вложенный массив содержит пару «ключ-значение» из self.

  • to_h: возвращает self, если объект является Hash; если это подкласс Hash, возвращает Hash, содержащий записи из self.

  • to_hash: возвращает self.

  • to_proc: возвращает процедуру, сопоставляющую заданный ключ с его значением.

Методы преобразования ключей и значений

  • invert: возвращает хеш, в котором каждая пара «ключ-значение» обращена.

  • transform_keys: возвращает копию self с изменёнными ключами.

  • transform_keys!: изменяет ключи в self

  • transform_values: возвращает копию self с изменёнными значениями.

  • transform_values!: изменяет значения в self.

Открытые методы класса

Hash[] → new_empty_hash Показать исходный код
Hash[other_hash] → new_hash
Hash[ [*2_element_arrays] ] → new_hash
Hash[*objects] → new_hash
static VALUE
rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
{
    VALUE hash, tmp;

    if (argc == 1) {
        tmp = rb_hash_s_try_convert(Qnil, argv[0]);
        if (!NIL_P(tmp)) {
            if (!RHASH_EMPTY_P(tmp)  && rb_hash_compare_by_id_p(tmp)) {
                /* hash_copy for non-empty hash will copy compare_by_identity
                   flag, but we don't want it copied. Work around by
                   converting hash to flattened array and using that. */
                tmp = rb_hash_to_a(tmp);
            }
            else {
                hash = hash_alloc(klass);
                if (!RHASH_EMPTY_P(tmp))
                    hash_copy(hash, tmp);
                return hash;
            }
        }
        else {
            tmp = rb_check_array_type(argv[0]);
        }

        if (!NIL_P(tmp)) {
            long i;

            hash = hash_alloc(klass);
            for (i = 0; i < RARRAY_LEN(tmp); ++i) {
                VALUE e = RARRAY_AREF(tmp, i);
                VALUE v = rb_check_array_type(e);
                VALUE key, val = Qnil;

                if (NIL_P(v)) {
                    rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
                             rb_builtin_class_name(e), i);
                }
                switch (RARRAY_LEN(v)) {
                  default:
                    rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
                             RARRAY_LEN(v));
                  case 2:
                    val = RARRAY_AREF(v, 1);
                  case 1:
                    key = RARRAY_AREF(v, 0);
                    rb_hash_aset(hash, key, val);
                }
            }
            return hash;
        }
    }
    if (argc % 2 != 0) {
        rb_raise(rb_eArgError, "odd number of arguments for Hash");
    }

    hash = hash_alloc(klass);
    rb_hash_bulk_insert(argc, argv, hash);
    hash_verify(hash);
    return hash;
}

Возвращает новый объект Hash, заполненный переданными объектами, если они есть. См. Hash::new.

Если аргумент не передан, возвращает новый пустой хеш.

Если передан один аргумент other_hash, являющийся хешем, возвращает новый хеш, инициализированный записями из этого хеша (но не его default или default_proc):

h = {foo: 0, bar: 1, baz: 2}
Hash[h] # => {foo: 0, bar: 1, baz: 2}

Если передан один аргумент 2_element_arrays, являющийся массивом массивов из двух элементов, возвращает новый хеш, в котором каждый переданный массив из двух элементов образует запись «ключ-значение»:

Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {foo: 0, bar: 1}

Если передано чётное число аргументов objects, возвращает новый хеш, в котором каждая следующая пара аргументов образует запись «ключ-значение»:

Hash[:foo, 0, :bar, 1] # => {foo: 0, bar: 1}

Вызывает ArgumentError, если список аргументов не соответствует ни одному из перечисленных выше вариантов.

См. также Методы создания хеша.

new(default_value = nil, capacity: 0) → new_hash Показать исходный код
new(capacity: 0) {|self, key| ... } → new_hash
# File hash.rb, line 37
def initialize(ifnone = (ifnone_unset = true), capacity: 0, &block)
  Primitive.rb_hash_init(capacity, ifnone_unset, ifnone, block)
end

Возвращает новый пустой объект Hash.

Инициализирует значения Hash#default и Hash#default_proc, определяющие поведение в случае, когда заданный ключ не найден; см. Ключ не найден?.

По умолчанию хеш содержит значения nil как для default, так и для default_proc:

h = Hash.new        # => {}
h.default           # => nil
h.default_proc      # => nil

Если передан аргумент default_value, задаёт значение default для хеша:

h = Hash.new(false) # => {}
h.default           # => false
h.default_proc      # => nil

Если передан блок, задаёт значение default_proc:

h = Hash.new {|hash, key| "Hash #{hash}: Default value for #{key}" }
h.default      # => nil
h.default_proc # => #<Proc:0x00000289b6fa7048 (irb):185>
h[:nosuch]     # => "Hash {}: Default value for nosuch"

Вызывает ArgumentError, если переданы и default_value, и блок.

Если необязательный именованный аргумент capacity передан с положительным целочисленным значением n, инициализирует хеш ёмкостью, достаточной для размещения n записей без изменения размера.

См. также Методы создания хеша.

ruby2_keywords_hash(hash) → hash Показать исходный код
static VALUE
rb_hash_s_ruby2_keywords_hash(VALUE dummy, VALUE hash)
{
    Check_Type(hash, T_HASH);
    VALUE tmp = rb_hash_dup(hash);
    if (RHASH_EMPTY_P(hash) && rb_hash_compare_by_id_p(hash)) {
        rb_hash_compare_by_id(tmp);
    }
    RHASH(tmp)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
    return tmp;
}

Создаёт копию заданного хеша и добавляет флаг ruby2_keywords. Этот метод не предназначен для обычного использования; он нужен для отладки, исследований и некоторых действительно необходимых случаев, например десериализации аргументов.

h = {k: 1}
h = Hash.ruby2_keywords_hash(h)
def foo(k: 42)
  k
end
foo(*[h]) #=> 1 with neither a warning or an error
ruby2_keywords_hash?(hash) → true or false Показать исходный код
static VALUE
rb_hash_s_ruby2_keywords_hash_p(VALUE dummy, VALUE hash)
{
    Check_Type(hash, T_HASH);
    return RBOOL(RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS);
}

Проверяет, установлен ли для заданного хеша флаг Module#ruby2_keywords (или Proc#ruby2_keywords). Этот метод не предназначен для обычного использования; он нужен для отладки, исследований и некоторых действительно необходимых случаев, например сериализации аргументов.

ruby2_keywords def foo(*args)
  Hash.ruby2_keywords_hash?(args.last)
end
foo(k: 1)   #=> true
foo({k: 1}) #=> false
try_convert(object) → object, new_hash, or nil Показать исходный код
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
    return rb_check_hash_type(hash);
}

Если object является хешем, возвращает object.

В противном случае, если object отвечает на вызов :to_hash, вызывает object.to_hash; возвращает результат, если он является хешем, или вызывает TypeError, если это не так.

В противном случае, если object не отвечает на вызов :to_hash, возвращает nil.

Общедоступные методы экземпляра

self < other → true or false Показать исходный код
static VALUE
rb_hash_lt(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) >= RHASH_SIZE(other)) return Qfalse;
    return hash_le(hash, other);
}

Возвращает, являются ли записи self собственным подмножеством записей other:

h = {foo: 0, bar: 1}
h < {foo: 0, bar: 1, baz: 2} # => true   # Proper subset.
h < {baz: 2, bar: 1, foo: 0} # => true   # Order may differ.
h < h                        # => false  # Not a proper subset.
h < {bar: 1, foo: 0}         # => false  # Not a proper subset.
h < {foo: 0, bar: 1, baz: 2} # => false  # Different key.
h < {foo: 0, bar: 1, baz: 2} # => false  # Different value.

См. Включение хешей.

Вызывает TypeError, если other_hash не является хешем и не может быть преобразован в хеш.

Связанные материалы: см. Методы сравнения.

self <= other → true or false Показать исходный код
static VALUE
rb_hash_le(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) > RHASH_SIZE(other)) return Qfalse;
    return hash_le(hash, other);
}

Возвращает, являются ли записи self подмножеством записей other:

h0 = {foo: 0, bar: 1}
h1 = {foo: 0, bar: 1, baz: 2}
h0 <= h0 # => true
h0 <= h1 # => true
h1 <= h0 # => false

См. Включение хешей.

Вызывает TypeError, если other_hash не является хешем и не может быть преобразован в хеш.

Связанные материалы: см. Методы сравнения.

self == object → true or false Показать исходный код
static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}

Возвращает, равны ли self и object.

Возвращает true, если выполняются все следующие условия:

  • object является объектом Hash (или может быть преобразован в него).

  • self и object имеют одинаковые ключи (независимо от порядка).

  • Для каждого ключа key выполняется self[key] == object[key].

В противном случае возвращает false.

Примеры:

h =  {foo: 0, bar: 1}
h == {foo: 0, bar: 1} # => true   # Equal entries (same order)
h == {bar: 1, foo: 0} # => true   # Equal entries (different order).
h == 1                            # => false  # Object not a hash.
h == {}                           # => false  # Different number of entries.
h == {foo: 0, bar: 1} # => false  # Different key.
h == {foo: 0, bar: 1} # => false  # Different value.

Связанные материалы: см. Методы сравнения.

self > other_hash → true or false Показать исходный код
static VALUE
rb_hash_gt(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) <= RHASH_SIZE(other)) return Qfalse;
    return hash_le(other, hash);
}

Возвращает true, если записи self являются собственным надмножеством записей other_hash, и false в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h > {foo: 0, bar: 1}         # => true   # Proper superset.
h > {bar: 1, foo: 0}         # => true   # Order may differ.
h > h                        # => false  # Not a proper superset.
h > {baz: 2, bar: 1, foo: 0} # => false  # Not a proper superset.
h > {foo: 0, bar: 1}         # => false  # Different key.
h > {foo: 0, bar: 1}         # => false  # Different value.

См. Включение хешей.

Вызывает TypeError, если other_hash не является хешем и не может быть преобразован в хеш.

Связанные материалы: см. Методы сравнения.

self >= other_hash → true or false Показать исходный код
static VALUE
rb_hash_ge(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) < RHASH_SIZE(other)) return Qfalse;
    return hash_le(other, hash);
}

Возвращает true, если записи self являются надмножеством записей other_hash, и false в противном случае:

h0 = {foo: 0, bar: 1, baz: 2}
h1 = {foo: 0, bar: 1}
h0 >= h1 # => true
h0 >= h0 # => true
h1 >= h0 # => false

См. Включение хешей.

Вызывает TypeError, если other_hash не является хешем и не может быть преобразован в хеш.

Связанные материалы: см. Методы сравнения.

self[key] → object Показать исходный код
VALUE
rb_hash_aref(VALUE hash, VALUE key)
{
    st_data_t val;

    if (hash_stlike_lookup(hash, key, &val)) {
        return (VALUE)val;
    }
    else {
        return rb_hash_default_value(hash, key);
    }
}

Ищет ключ хеша, эквивалентный заданному key; см. Эквивалентность ключей хеша.

Если ключ найден, возвращает его значение:

{foo: 0, bar: 1, baz: 2}
h[:bar] # => 1

В противном случае возвращает значение по умолчанию (см. Значение хеша по умолчанию).

Связанные материалы: []=; см. также Методы получения.

self[key] = object → object Показать исходный код
VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    bool iter_p = hash_iterating_p(hash);

    rb_hash_modify(hash);

    if (!RHASH_STRING_KEY_P(hash, key)) {
        RHASH_UPDATE_ITER(hash, iter_p, key, hash_aset, val);
    }
    else {
        RHASH_UPDATE_ITER(hash, iter_p, key, hash_aset_str, val);
    }
    return val;
}

Связывает заданное object с заданным key; возвращает object.

Ищет ключ хеша, эквивалентный заданному key; см. Эквивалентность ключей хеша.

Если ключ найден, заменяет его значение на заданное object; порядок не изменяется (см. Порядок записей):

h = {foo: 0, bar: 1}
h[:foo] = 2 # => 2
h[:foo]     # => 2

Если key не найден, создает новую запись для заданных key и object; новая запись будет последней в порядке (см. Порядок записей):

h = {foo: 0, bar: 1}
h[:baz] = 2 # => 2
h[:baz]     # => 2
h           # => {:foo=>0, :bar=>1, :baz=>2}

Связанные материалы: []; см. также Методы присваивания.

Также имеет псевдоним: store
any? → true or false Показать исходный код
any?(entry) → true or false
any? {|key, value| ... } → true or false
static VALUE
rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
{
    VALUE args[2];
    args[0] = Qfalse;

    rb_check_arity(argc, 0, 1);
    if (RHASH_EMPTY_P(hash)) return Qfalse;
    if (argc) {
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        args[1] = argv[0];

        rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
    }
    else {
        if (!rb_block_given_p()) {
            /* yields pairs, never false */
            return Qtrue;
        }
        if (rb_block_pair_yield_optimizable())
            rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
        else
            rb_hash_foreach(hash, any_p_i, (VALUE)args);
    }
    return args[0];
}

Возвращает true, если какой-либо элемент удовлетворяет заданному условию; в противном случае возвращает false.

Если self не содержит элементов, возвращает false, а аргумент и блок не используются; иначе работает описанным ниже образом.

Без аргумента и блока возвращает true, если self не пуст, и false в противном случае.

С аргументом entry и без блока возвращает true, если для любого ключа key выполняется self.assoc(key) == entry, и false в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h.assoc(:bar)     # => [:bar, 1]
h.any?([:bar, 1]) # => true
h.any?([:bar, 0]) # => false

Без аргумента, но с блоком, вызывает блок для каждой пары ключ-значение; возвращает true, если блок возвращает истинное значение, и false в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h.any? {|key, value| value < 3 } # => true
h.any? {|key, value| value > 3 } # => false

Если заданы и аргумент entry, и блок, выводит предупреждение и игнорирует блок.

Связанные материалы: Enumerable#any? (этот метод переопределяет его); см. также Методы получения.

assoc(key) → entry or nil Показать исходный код
static VALUE
rb_hash_assoc(VALUE hash, VALUE key)
{
    VALUE args[2];

    if (RHASH_EMPTY_P(hash)) return Qnil;

    if (RHASH_ST_TABLE_P(hash) && !RHASH_IDENTHASH_P(hash)) {
        VALUE value = Qundef;
        st_table assoctable = *RHASH_ST_TABLE(hash);
        assoctable.type = &(struct st_hash_type){
            .compare = assoc_cmp,
            .hash = assoctable.type->hash,
        };
        VALUE arg = (VALUE)&(struct assoc_arg){
            .tbl = &assoctable,
            .key = (st_data_t)key,
        };

        if (RB_OBJ_FROZEN(hash)) {
            value = assoc_lookup(arg);
        }
        else {
            hash_iter_lev_inc(hash);
            value = rb_ensure(assoc_lookup, arg, hash_foreach_ensure, hash);
        }
        hash_verify(hash);
        if (!UNDEF_P(value)) return rb_assoc_new(key, value);
    }

    args[0] = key;
    args[1] = Qnil;
    rb_hash_foreach(hash, assoc_i, (VALUE)args);
    return args[1];
}

Если заданный key найден, возвращает его запись в виде массива из двух элементов, содержащего этот ключ и его значение:

h = {foo: 0, bar: 1, baz: 2}
h.assoc(:bar) # => [:bar, 1]

Если ключ не найден, возвращает nil.

Связанные материалы: см. Методы получения.

clear → self Показать исходный код
VALUE
rb_hash_clear(VALUE hash)
{
    rb_hash_modify_check(hash);

    if (hash_iterating_p(hash)) {
        rb_hash_foreach(hash, clear_i, 0);
    }
    else if (RHASH_AR_TABLE_P(hash)) {
        ar_clear(hash);
    }
    else {
        st_clear(RHASH_ST_TABLE(hash));
        compact_after_delete(hash);
    }

    return hash;
}

Удаляет все записи из self; возвращает опустошенный self.

Связанные материалы: см. Методы удаления.

compact → new_hash Показать исходный код
static VALUE
rb_hash_compact(VALUE hash)
{
    VALUE result = rb_hash_dup(hash);
    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_foreach(result, delete_if_nil, result);
        compact_after_delete(result);
    }
    else if (rb_hash_compare_by_id_p(hash)) {
        result = rb_hash_compare_by_id(result);
    }
    return result;
}

Возвращает копию self без записей со значением nil:

h = {foo: 0, bar: nil, baz: 2, bat: nil}
h.compact # => {foo: 0, baz: 2}

Связанные материалы: см. Методы удаления.

compact! → self or nil Показать исходный код
static VALUE
rb_hash_compact_bang(VALUE hash)
{
    st_index_t n;
    rb_hash_modify_check(hash);
    n = RHASH_SIZE(hash);
    if (n) {
        rb_hash_foreach(hash, delete_if_nil, hash);
        if (n != RHASH_SIZE(hash))
            return hash;
    }
    return Qnil;
}

Если self содержит записи со значением nil, возвращает self без записей со значением nil; в противном случае возвращает nil:

h = {foo: 0, bar: nil, baz: 2, bat: nil}
h.compact!
h          # => {foo: 0, baz: 2}
h.compact! # => nil

Связанные материалы: см. Методы удаления.

compare_by_identity → self Показать исходный код
VALUE
rb_hash_compare_by_id(VALUE hash)
{
    VALUE tmp;
    st_table *identtable;

    if (rb_hash_compare_by_id_p(hash)) return hash;

    rb_hash_modify_check(hash);
    if (hash_iterating_p(hash)) {
        rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
    }

    if (RHASH_TABLE_EMPTY_P(hash)) {
        // Fast path: There's nothing to rehash, so we don't need a `tmp` table.
        // We're most likely an AR table, so this will need an allocation.
        ar_force_convert_table(hash, __FILE__, __LINE__);
        HASH_ASSERT(RHASH_ST_TABLE_P(hash));

        RHASH_ST_TABLE(hash)->type = &identhash;
    }
    else {
        // Slow path: Need to rehash the members of `self` into a new
        // `tmp` table using the new `identhash` compare/hash functions.
        tmp = hash_alloc(0);
        hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
        identtable = RHASH_ST_TABLE(tmp);

        rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
        rb_hash_free(hash);

        // We know for sure `identtable` is an st table,
        // so we can skip `ar_force_convert_table` here.
        RHASH_ST_TABLE_SET(hash, identtable);
        RHASH_ST_CLEAR(tmp);
    }

    return hash;
}

Настраивает self на сравнение ключей по идентичности (а не только по равенству); возвращает self:

По умолчанию два ключа считаются одинаковыми тогда и только тогда, когда они являются равными объектами (согласно методу eql?):

h = {}
h['x'] = 0
h['x'] = 1 # Overwrites.
h # => {"x"=>1}

После вызова этого метода два ключа считаются одинаковыми тогда и только тогда, когда они являются одним и тем же объектом:

h.compare_by_identity
h['x'] = 2 # Does not overwrite.
h # => {"x"=>1, "x"=>2}

Связанные материалы: compare_by_identity?; см. также Методы сравнения.

compare_by_identity? → true or false Показать исходный код
VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    return RBOOL(RHASH_IDENTHASH_P(hash));
}

Возвращает, был ли вызван метод compare_by_identity:

h = {}
h.compare_by_identity? # => false
h.compare_by_identity
h.compare_by_identity? # => true

Связанные материалы: compare_by_identity; см. также Методы сравнения.

default → object Показать исходный код
default(key) → object
static VALUE
rb_hash_default(int argc, VALUE *argv, VALUE hash)
{
    VALUE ifnone;

    rb_check_arity(argc, 0, 1);
    ifnone = RHASH_IFNONE(hash);
    if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
        if (argc == 0) return Qnil;
        return call_default_proc(ifnone, hash, argv[0]);
    }
    return ifnone;
}

Возвращает значение по умолчанию для заданного key. Возвращаемое значение определяется либо процедурой по умолчанию, либо значением по умолчанию. См. Значение хеша по умолчанию.

Без аргумента возвращает текущее значение по умолчанию:

h = {}
h.default # => nil

Если задан key, возвращает значение по умолчанию для key независимо от того, существует ли этот ключ:

h = Hash.new { |hash, key| hash[key] = "No key #{key}"}
h[:foo] = "Hello"
h.default(:foo) # => "No key foo"
default = value → object Показать исходный код
VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
    rb_hash_modify_check(hash);
    SET_DEFAULT(hash, ifnone);
    return ifnone;
}

Устанавливает значение по умолчанию равным value; возвращает value:

h = {}
h.default # => nil
h.default = false # => false
h.default # => false

См. Значение хеша по умолчанию.

default_proc → proc or nil Показать исходный код
static VALUE
rb_hash_default_proc(VALUE hash)
{
    if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
        return RHASH_IFNONE(hash);
    }
    return Qnil;
}

Возвращает процедуру по умолчанию для self (см. Значение хеша по умолчанию):

h = {}
h.default_proc # => nil
h.default_proc = proc {|hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
default_proc = proc → proc Показать исходный код
VALUE
rb_hash_set_default_proc(VALUE hash, VALUE proc)
{
    VALUE b;

    rb_hash_modify_check(hash);
    if (NIL_P(proc)) {
        SET_DEFAULT(hash, proc);
        return proc;
    }
    b = rb_check_convert_type_with_id(proc, T_DATA, "Proc", idTo_proc);
    if (NIL_P(b) || !rb_obj_is_proc(b)) {
        rb_raise(rb_eTypeError,
                 "wrong default_proc type %s (expected Proc)",
                 rb_obj_classname(proc));
    }
    proc = b;
    SET_PROC_DEFAULT(hash, proc);
    return proc;
}

Устанавливает процедуру по умолчанию для self равной proc (см. Значение хеша по умолчанию):

h = {}
h.default_proc # => nil
h.default_proc = proc { |hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
h.default_proc = nil
h.default_proc # => nil
delete(key) → value or nil Показать исходный код
delete(key) {|key| ... } → object
static VALUE
rb_hash_delete_m(VALUE hash, VALUE key)
{
    VALUE val;

    rb_hash_modify_check(hash);
    val = rb_hash_delete_entry(hash, key);

    if (!UNDEF_P(val)) {
        compact_after_delete(hash);
        return val;
    }
    else {
        if (rb_block_given_p()) {
            return rb_yield(key);
        }
        else {
            return Qnil;
        }
    }
}

Если запись для заданного key найдена, удаляет ее и возвращает связанное с ней значение; в противном случае возвращает nil или вызывает заданный блок.

Если блок не задан и key найден, удаляет запись и возвращает ее значение:

h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {foo: 0, baz: 2}

Если блок не задан и key не найден, возвращает nil.

Если блок задан и key найден, игнорирует блок, удаляет запись и возвращает ее значение:

h = {foo: 0, bar: 1, baz: 2}
h.delete(:baz) { |key| raise 'Will never happen'} # => 2
h # => {foo: 0, bar: 1}

Если блок задан и key не найден, вызывает блок и возвращает результат его выполнения:

h = {foo: 0, bar: 1, baz: 2}
h.delete(:nosuch) { |key| "Key #{key} not found" } # => "Key nosuch not found"
h # => {foo: 0, bar: 1, baz: 2}

Связанные материалы: см. Методы удаления.

delete_if {|key, value| ... } → self Показать исходный код
delete_if → new_enumerator
VALUE
rb_hash_delete_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        rb_hash_foreach(hash, delete_if_i, hash);
        compact_after_delete(hash);
    }
    return hash;
}

Если блок задан, вызывает его для каждой пары ключ-значение, удаляет каждую запись, для которой блок возвращает истинное значение, и возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.delete_if {|key, value| value > 0 } # => {foo: 0}

Если блок не задан, возвращает новый Enumerator.

Связанные материалы: см. Методы удаления.

dig(key, *identifiers) → object Показать исходный код
static VALUE
rb_hash_dig(int argc, VALUE *argv, VALUE self)
{
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    self = rb_hash_aref(self, *argv);
    if (!--argc) return self;
    ++argv;
    return rb_obj_dig(argc, argv, self, Qnil);
}

Находит и возвращает объект во вложенных объектах, указанных с помощью key и identifiers.

Вложенные объекты могут быть экземплярами различных классов. См. Методы Dig.

Вложенные хеши:

h = {foo: {bar: {baz: 2}}}
h.dig(:foo) # => {bar: {baz: 2}}
h.dig(:foo, :bar) # => {baz: 2}
h.dig(:foo, :bar, :baz) # => 2
h.dig(:foo, :bar, :BAZ) # => nil

Вложенные хеши и массивы:

h = {foo: {bar: [:a, :b, :c]}}
h.dig(:foo, :bar, 2) # => :c

Если такой объект не найден, возвращает значение хеша по умолчанию:

h = {foo: {bar: [:a, :b, :c]}}
h.dig(:hello) # => nil
h.default_proc = -> (hash, _key) { hash }
h.dig(:hello, :world)
# => {:foo=>{:bar=>[:a, :b, :c]}}

Связанные материалы: Методы получения.

each
Псевдоним для: each_pair
each_key {|key| ... } → self Показать исходный код
each_key → new_enumerator
static VALUE
rb_hash_each_key(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_foreach(hash, each_key_i, 0);
    return hash;
}

Если блок задан, вызывает его для каждого ключа; возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.each_key {|key| puts key }  # => {foo: 0, bar: 1, baz: 2}

Результат:

foo
bar
baz

Если блок не задан, возвращает новый Enumerator.

Связанные материалы: см. Методы перебора.

each_pair {|key, value| ... } → self Показать исходный код
each_pair → new_enumerator
static VALUE
rb_hash_each_pair(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    if (rb_block_pair_yield_optimizable())
        rb_hash_foreach(hash, each_pair_i_fast, 0);
    else
        rb_hash_foreach(hash, each_pair_i, 0);
    return hash;
}

Если блок задан, вызывает его для каждой пары ключ-значение; возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.each_pair {|key, value| puts "#{key}: #{value}"} # => {foo: 0, bar: 1, baz: 2}

Результат:

foo: 0
bar: 1
baz: 2

Если блок не задан, возвращает новый Enumerator.

Связанные материалы: см. Методы перебора.

Также имеет псевдоним: each
each_value {|value| ... } → self Показать исходный код
each_value → new_enumerator
static VALUE
rb_hash_each_value(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_foreach(hash, each_value_i, 0);
    return hash;
}

Если блок задан, вызывает его для каждого значения; возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.each_value {|value| puts value } # => {foo: 0, bar: 1, baz: 2}

Результат:

0
1
2

Если блок не задан, возвращает новый Enumerator.

Связанные материалы: см. Методы перебора.

empty? → true or false Показать исходный код
VALUE
rb_hash_empty_p(VALUE hash)
{
    return RBOOL(RHASH_EMPTY_P(hash));
}

Возвращает true, если в хеше нет записей, и false в противном случае:

{}.empty? # => true
{foo: 0}.empty? # => false

Связанные материалы: см. Методы проверки.

eql?(object) → true or false Показать исходный код
static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}

Возвращает true, если выполняются все следующие условия:

  • Заданный object является объектом Hash.

  • self и object имеют одинаковые ключи (независимо от порядка).

  • Для каждого ключа key выполняется self[key].eql?(object[key]).

В противном случае возвращает false.

h1 = {foo: 0, bar: 1, baz: 2}
h2 = {foo: 0, bar: 1, baz: 2}
h1.eql? h2 # => true
h3 = {baz: 2, bar: 1, foo: 0}
h1.eql? h3 # => true

Связанные материалы: см. Методы проверки.

except(*keys) → new_hash Показать исходный код
static VALUE
rb_hash_except(int argc, VALUE *argv, VALUE hash)
{
    int i;
    VALUE key, result;

    result = hash_dup_with_compare_by_id(hash);

    for (i = 0; i < argc; i++) {
        key = argv[i];
        rb_hash_delete(result, key);
    }
    compact_after_delete(result);

    return result;
}

Возвращает копию self без записей для заданных keys; все keys, которые не найдены, игнорируются:

h = {foo:0, bar: 1, baz: 2} # => {:foo=>0, :bar=>1, :baz=>2}
h.except(:baz, :foo)        # => {:bar=>1}
h.except(:bar, :nosuch)     # => {:foo=>0, :baz=>2}

Связанные материалы: см. Методы удаления.

fetch(key) → object Показать исходный код
fetch(key, default_value) → object
fetch(key) {|key| ... } → object
static VALUE
rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
{
    VALUE key;
    st_data_t val;
    long block_given;

    rb_check_arity(argc, 1, 2);
    key = argv[0];

    block_given = rb_block_given_p();
    if (block_given && argc == 2) {
        rb_warn("block supersedes default value argument");
    }

    if (hash_stlike_lookup(hash, key, &val)) {
        return (VALUE)val;
    }
    else {
        if (block_given) {
            return rb_yield(key);
        }
        else if (argc == 1) {
            VALUE desc = rb_protect(rb_inspect, key, 0);
            if (NIL_P(desc)) {
                desc = rb_any_to_s(key);
            }
            desc = rb_str_ellipsize(desc, 65);
            rb_key_err_raise(rb_sprintf("key not found: %"PRIsVALUE, desc), hash, key);
        }
        else {
            return argv[1];
        }
    }
}

Если блок не задан, возвращает значение для заданного key, если оно найдено;

h = {foo: 0, bar: 1, baz: 2}
h.fetch(:bar)  # => 1

Если ключ не найден, возвращает default_value, если он задан, или в противном случае вызывает KeyError:

h.fetch(:nosuch, :default) # => :default
h.fetch(:nosuch)           # Raises KeyError.

Если блок задан, вызывает его с key и возвращает результат выполнения блока:

{}.fetch(:nosuch) {|key| "No key #{key}"} # => "No key nosuch"

Обратите внимание, что этот метод не использует значения ни default, ни default_proc.

Связанные материалы: см. Методы получения.

fetch_values(*keys) → new_array Показать исходный код
fetch_values(*keys) {|key| ... } → new_array
static VALUE
rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
{
    VALUE result = rb_ary_new2(argc);
    long i;

    for (i=0; i<argc; i++) {
        rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
    }
    return result;
}

Если все заданные keys найдены, возвращает новый массив со значениями, связанными с заданными keys:

h = {foo: 0, bar: 1, baz: 2}
h.fetch_values(:baz, :foo) # => [2, 0]

Если какие-либо заданные keys не найдены и блок задан, вызывает блок для каждого ненайденного ключа и использует результат выполнения блока как значение для этого ключа:

h.fetch_values(:bar, :foo, :bad, :bam) {|key| key.to_s}
# => [1, 0, "bad", "bam"]

Если какие-либо заданные keys не найдены и блок не задан, вызывает KeyError.

Связанные материалы: см. Методы получения.

filter
Псевдоним для: select
filter!
Псевдоним для: select!
flatten(depth = 1) → new_array Показать исходный код
static VALUE
rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
{
    VALUE ary;

    rb_check_arity(argc, 0, 1);

    if (argc) {
        int level = NUM2INT(argv[0]);

        if (level == 0) return rb_hash_to_a(hash);

        ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
        rb_hash_foreach(hash, flatten_i, ary);
        level--;

        if (level > 0) {
            VALUE ary_flatten_level = INT2FIX(level);
            rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
        }
        else if (level < 0) {
            /* flatten recursively */
            rb_funcallv(ary, id_flatten_bang, 0, 0);
        }
    }
    else {
        ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
        rb_hash_foreach(hash, flatten_i, ary);
    }

    return ary;
}

При положительном целом числе depth возвращает новый массив, полученный рекурсивным уплощением self до заданного уровня depth.

На каждом уровне рекурсии:

  • Каждый элемент, значением которого является массив, «уплощается» (то есть заменяется отдельными элементами этого массива); см. Array#flatten.

  • Каждый элемент, значением которого не является массив, остается без изменений, даже если его значение — объект с методом экземпляра flatten (например, хеш).

Примеры; обратите внимание, что запись foo: {bar: 1, baz: 2} никогда не уплощается.

h = {foo: {bar: 1, baz: 2}, bat: [:bam, [:bap, [:bah]]]}
h.flatten(1) # => [:foo, {:bar=>1, :baz=>2}, :bat, [:bam, [:bap, [:bah]]]]
h.flatten(2) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, [:bap, [:bah]]]
h.flatten(3) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, [:bah]]
h.flatten(4) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]
h.flatten(5) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]

При отрицательном целом числе depth уплощает все уровни:

h.flatten(-1) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]

При depth, равном нулю, возвращает результат, эквивалентный to_a:

h.flatten(0) # => [[:foo, {:bar=>1, :baz=>2}], [:bat, [:bam, [:bap, [:bah]]]]]

Связанные материалы: см. Методы преобразования.

has_key?
Псевдоним для: include?
has_value?(value) → true or false Показать исходный код
static VALUE
rb_hash_has_value(VALUE hash, VALUE val)
{
    VALUE data[2];

    data[0] = Qfalse;
    data[1] = val;
    rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
    return data[0];
}

Возвращает, является ли value значением в self.

Связанные методы: Методы для проверки.

Также имеет псевдоним: value?
hash → an_integer Показать исходный код
static VALUE
rb_hash_hash(VALUE hash)
{
    st_index_t size = RHASH_SIZE(hash);
    st_index_t hval = rb_hash_start(size);
    hval = rb_hash_uint(hval, (st_index_t)rb_hash_hash);
    if (size) {
        rb_hash_foreach(hash, hash_i, (VALUE)&hval);
    }
    hval = rb_hash_end(hval);
    return ST2FIX(hval);
}

Возвращает целочисленный хеш-код хеша.

Два хеша имеют одинаковый хеш-код, если их содержимое одинаково (независимо от порядка):

h1 = {foo: 0, bar: 1, baz: 2}
h2 = {baz: 2, bar: 1, foo: 0}
h2.hash == h1.hash # => true
h2.eql? h1 # => true

Связанные методы: см. Методы для проверки.

include?(key) → true or false Показать исходный код
VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

Возвращает, является ли key ключом в self:

h = {foo: 0, bar: 1, baz: 2}
h.include?(:bar) # => true
h.include?(:BAR) # => false

Связанные методы: Методы для проверки.

Также имеет псевдонимы: member?, has_key?, key?
initialize_copy Показать исходный код
static VALUE
rb_hash_replace(VALUE hash, VALUE hash2)
{
    rb_hash_modify_check(hash);
    if (hash == hash2) return hash;
    if (hash_iterating_p(hash)) {
        rb_raise(rb_eRuntimeError, "can't replace hash during iteration");
    }
    hash2 = to_hash(hash2);

    COPY_DEFAULT(hash, hash2);

    if (RHASH_AR_TABLE_P(hash)) {
        hash_ar_free_and_clear_table(hash);
    }
    else {
        hash_st_free_and_clear_table(hash);
    }

    hash_copy(hash, hash2);

    return hash;
}
Также имеет псевдоним: replace
inspect → new_string Показать исходный код
static VALUE
rb_hash_inspect(VALUE hash)
{
    if (RHASH_EMPTY_P(hash))
        return rb_usascii_str_new2("{}");
    return rb_exec_recursive(inspect_hash, hash, 0);
}

Возвращает новую строку, содержащую записи хеша:

h = {foo: 0, bar: 1, baz: 2}
h.inspect # => "{foo: 0, bar: 1, baz: 2}"

Связанные методы: см. Методы преобразования.

Также имеет псевдоним: to_s
invert → new_hash Показать исходный код
static VALUE
rb_hash_invert(VALUE hash)
{
    VALUE h = rb_hash_new_with_size(RHASH_SIZE(hash));

    rb_hash_foreach(hash, rb_hash_invert_i, h);
    return h;
}

Возвращает новый хеш с переставленными местами ключами и значениями каждой пары:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.invert
h1 # => {0=>:foo, 1=>:bar, 2=>:baz}

Перезаписывает повторяющиеся новые ключи (см. Порядок записей):

h = {foo: 0, bar: 0, baz: 0}
h.invert # => {0=>:baz}

Связанные методы: см. Методы преобразования ключей и значений.

keep_if {|key, value| ... } → self Показать исходный код
keep_if → new_enumerator
static VALUE
rb_hash_keep_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        rb_hash_foreach(hash, keep_if_i, hash);
    }
    return hash;
}

Если передан блок, вызывает его для каждой пары ключ-значение; сохраняет запись, если блок возвращает истинное значение, иначе удаляет её; возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.keep_if { |key, value| key.start_with?('b') } # => {bar: 1, baz: 2}

Если блок не передан, возвращает новый Enumerator.

Связанные методы: см. Методы удаления.

key(value) → key or nil Показать исходный код
static VALUE
rb_hash_key(VALUE hash, VALUE value)
{
    VALUE args[2];

    args[0] = value;
    args[1] = Qnil;

    rb_hash_foreach(hash, key_i, (VALUE)args);

    return args[1];
}

Возвращает ключ первой найденной записи с заданным значением value (см. Порядок записей):

h = {foo: 0, bar: 2, baz: 2}
h.key(0) # => :foo
h.key(2) # => :bar

Возвращает nil, если такое значение не найдено.

Связанные методы: см. Методы получения.

key?
Псевдоним для: include?
keys → new_array Показать исходный код
VALUE
rb_hash_keys(VALUE hash)
{
    st_index_t size = RHASH_SIZE(hash);
    VALUE keys =  rb_ary_new_capa(size);

    if (size == 0) return keys;

    if (ST_DATA_COMPATIBLE_P(VALUE)) {
        RARRAY_PTR_USE(keys, ptr, {
            if (RHASH_AR_TABLE_P(hash)) {
                size = ar_keys(hash, ptr, size);
            }
            else {
                st_table *table = RHASH_ST_TABLE(hash);
                size = st_keys(table, ptr, size);
            }
        });
        rb_gc_writebarrier_remember(keys);
        rb_ary_set_len(keys, size);
    }
    else {
        rb_hash_foreach(hash, keys_i, keys);
    }

    return keys;
}

Возвращает новый массив, содержащий все ключи в self:

h = {foo: 0, bar: 1, baz: 2}
h.keys # => [:foo, :bar, :baz]

Связанные методы: см. Методы получения.

length
Псевдоним для: size
member?
Псевдоним для: include?
merge(*other_hashes) → new_hash Показать исходный код
merge(*other_hashes) { |key, old_value, new_value| ... } → new_hash
static VALUE
rb_hash_merge(int argc, VALUE *argv, VALUE self)
{
    return rb_hash_update(argc, argv, copy_compare_by_id(rb_hash_dup(self), self));
}

Каждый аргумент other_hash в other_hashes должен быть хешем.

Если переданы аргументы other_hashes и не передан блок, возвращает новый хеш, созданный путём слияния каждого последующего other_hash с копией self; возвращает эту копию; для каждой последующей записи в other_hash:

  • Если ключ новый, запись добавляется в конец self.

  • Если ключ повторяется, запись перезаписывает запись в self, не меняя её позицию.

Пример:

h = {foo: 0, bar: 1, baz: 2}
h1 = {bat: 3, bar: 4}
h2 = {bam: 5, bat:6}
h.merge(h1, h2) # => {foo: 0, bar: 4, baz: 2, bat: 6, bam: 5}

Если переданы аргументы other_hashes и блок, действует описанное выше, за исключением того, что при повторяющемся ключе перезаписывающая запись получает значение не из записи в other_hash, а из блока:

  • Блок вызывается с повторяющимся ключом и значениями из обоих хешей: self и other_hash.

  • Возвращаемое блоком значение становится новым значением записи в self.

Пример:

h = {foo: 0, bar: 1, baz: 2}
h1 = {bat: 3, bar: 4}
h2 = {bam: 5, bat:6}
h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value }
# => {foo: 0, bar: 5, baz: 2, bat: 9, bam: 5}

Если аргументы не переданы, возвращает копию self; переданный блок игнорируется.

Связанные методы: см. Методы присваивания.

merge!
Псевдоним для: update
rassoc(value) → new_array or nil Показать исходный код
static VALUE
rb_hash_rassoc(VALUE hash, VALUE obj)
{
    VALUE args[2];

    args[0] = obj;
    args[1] = Qnil;
    rb_hash_foreach(hash, rassoc_i, (VALUE)args);
    return args[1];
}

Выполняет поиск в self первой записи, значение которой равно == заданному value; см. Порядок записей.

Если запись найдена, возвращает её ключ и значение в виде массива из двух элементов; если запись не найдена, возвращает nil:

h = {foo: 0, bar: 1, baz: 1}
h.rassoc(1) # => [:bar, 1]

Связанные методы: см. Методы получения.

rehash → self Показать исходный код
VALUE
rb_hash_rehash(VALUE hash)
{
    VALUE tmp;
    st_table *tbl;

    if (hash_iterating_p(hash)) {
        rb_raise(rb_eRuntimeError, "rehash during iteration");
    }
    rb_hash_modify_check(hash);
    if (RHASH_AR_TABLE_P(hash)) {
        tmp = hash_alloc(0);
        rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);

        hash_ar_free_and_clear_table(hash);
        ar_copy(hash, tmp);
    }
    else if (RHASH_ST_TABLE_P(hash)) {
        st_table *old_tab = RHASH_ST_TABLE(hash);
        tmp = hash_alloc(0);

        hash_st_table_init(tmp, old_tab->type, old_tab->num_entries);
        tbl = RHASH_ST_TABLE(tmp);

        rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);

        hash_st_free(hash);
        RHASH_ST_TABLE_SET(hash, tbl);
        RHASH_ST_CLEAR(tmp);
    }
    hash_verify(hash);
    return hash;
}

Перестраивает хеш-таблицу для self, повторно вычисляя хеш-индекс для каждого ключа; возвращает self. Вызов этого метода гарантирует корректность хеш-таблицы.

Хеш-таблица становится недействительной, если хеш-значение ключа изменилось после создания записи. См. Изменение активного ключа хеша.

reject {|key, value| ... } → new_hash Показать исходный код
reject → new_enumerator
static VALUE
rb_hash_reject(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = hash_dup_with_compare_by_id(hash);
    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_foreach(result, delete_if_i, result);
        compact_after_delete(result);
    }
    return result;
}

Если передан блок, возвращает копию self, из которой удалена одна или несколько записей; вызывает блок для каждой пары ключ-значение; исключает запись из копии, если блок возвращает истинное значение, и включает её в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h.reject {|key, value| key.start_with?('b') }
# => {foo: 0}

Если блок не передан, возвращает новый Enumerator.

Связанные методы: см. Методы удаления.

reject! {|key, value| ... } → self or nil Показать исходный код
reject! → new_enumerator
static VALUE
rb_hash_reject_bang(VALUE hash)
{
    st_index_t n;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify(hash);
    n = RHASH_SIZE(hash);
    if (!n) return Qnil;
    rb_hash_foreach(hash, delete_if_i, hash);
    if (n == RHASH_SIZE(hash)) return Qnil;
    return hash;
}

Если передан блок, вызывает его с ключом и значением каждой записи; удаляет запись из self, если блок возвращает истинное значение.

Возвращает self, если были удалены какие-либо записи, и nil в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h.reject! {|key, value| value < 2 } # => {baz: 2}
h.reject! {|key, value| value < 2 } # => nil

Если блок не передан, возвращает новый Enumerator.

Связанные методы: см. Методы удаления.

replace(other_hash) → self

Заменяет всё содержимое self содержимым other_hash; возвращает self:

h = {foo: 0, bar: 1, baz: 2}
h.replace({bat: 3, bam: 4}) # => {bat: 3, bam: 4}

Также заменяет значение по умолчанию или процедуру self значением по умолчанию или процедурой other_hash.

h = {}
other = Hash.new(:ok)
h.replace(other)
h.default # => :ok

Связанные методы: см. Методы присваивания.

Псевдоним для: initialize_copy
select {|key, value| ... } → new_hash Показать исходный код
select → new_enumerator
static VALUE
rb_hash_select(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = hash_dup_with_compare_by_id(hash);
    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_foreach(result, keep_if_i, result);
        compact_after_delete(result);
    }
    return result;
}

Если передан блок, вызывает его с ключом и значением каждой записи; возвращает новый хеш, содержащий записи, для которых блок возвращает истинное значение:

h = {foo: 0, bar: 1, baz: 2}
h.select {|key, value| value < 2 } # => {foo: 0, bar: 1}

Если блок не передан, возвращает новый Enumerator.

Связанные методы: см. Методы удаления.

Также имеет псевдоним: filter
select! {|key, value| ... } → self or nil Показать исходный код
select! → new_enumerator
static VALUE
rb_hash_select_bang(VALUE hash)
{
    st_index_t n;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    n = RHASH_SIZE(hash);
    if (!n) return Qnil;
    rb_hash_foreach(hash, keep_if_i, hash);
    if (n == RHASH_SIZE(hash)) return Qnil;
    return hash;
}

Если передан блок, вызывает его с ключом и значением каждой записи; удаляет из self каждую запись, для которой блок возвращает false или nil.

Возвращает self, если были удалены какие-либо записи, и nil в противном случае:

h = {foo: 0, bar: 1, baz: 2}
h.select! {|key, value| value < 2 } # => {foo: 0, bar: 1}
h.select! {|key, value| value < 2 } # => nil

Если блок не передан, возвращает новый Enumerator.

Связанные методы: см. Методы удаления.

Также имеет псевдоним: filter!
shift → [key, value] or nil Показать исходный код
static VALUE
rb_hash_shift(VALUE hash)
{
    struct shift_var var;

    rb_hash_modify_check(hash);
    if (RHASH_AR_TABLE_P(hash)) {
        var.key = Qundef;
        if (!hash_iterating_p(hash)) {
            if (ar_shift(hash, &var.key, &var.val)) {
                return rb_assoc_new(var.key, var.val);
            }
        }
        else {
            rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
            if (!UNDEF_P(var.key)) {
                rb_hash_delete_entry(hash, var.key);
                return rb_assoc_new(var.key, var.val);
            }
        }
    }
    if (RHASH_ST_TABLE_P(hash)) {
        var.key = Qundef;
        if (!hash_iterating_p(hash)) {
            if (st_shift(RHASH_ST_TABLE(hash), &var.key, &var.val)) {
                return rb_assoc_new(var.key, var.val);
            }
        }
        else {
            rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
            if (!UNDEF_P(var.key)) {
                rb_hash_delete_entry(hash, var.key);
                return rb_assoc_new(var.key, var.val);
            }
        }
    }
    return Qnil;
}

Удаляет и возвращает первую запись self в виде массива из двух элементов; см. Порядок записей:

h = {foo: 0, bar: 1, baz: 2}
h.shift # => [:foo, 0]
h       # => {bar: 1, baz: 2}

Возвращает nil, если self пуст.

Связанные методы: см. Методы удаления.

size → integer Показать исходный код
VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}

Возвращает количество записей в self:

{foo: 0, bar: 1, baz: 2}.size # => 3

Связанные методы: см. Методы для проверки.

Также имеет псевдоним: length
slice(*keys) → new_hash Показать исходный код
static VALUE
rb_hash_slice(int argc, VALUE *argv, VALUE hash)
{
    int i;
    VALUE key, value, result;

    if (argc == 0 || RHASH_EMPTY_P(hash)) {
        return copy_compare_by_id(rb_hash_new(), hash);
    }
    result = copy_compare_by_id(rb_hash_new_with_size(argc), hash);

    for (i = 0; i < argc; i++) {
        key = argv[i];
        value = rb_hash_lookup2(hash, key, Qundef);
        if (!UNDEF_P(value))
            rb_hash_aset(result, key, value);
    }

    return result;
}

Возвращает новый хеш, содержащий записи из self для заданных keys; игнорирует ключи, которые не найдены:

h = {foo: 0, bar: 1, baz: 2}
h.slice(:baz, :foo, :nosuch) # => {baz: 2, foo: 0}

Связанные методы: см. Методы удаления.

store
Псевдоним для: []=
to_a → new_array Показать исходный код
static VALUE
rb_hash_to_a(VALUE hash)
{
    VALUE ary;

    ary = rb_ary_new_capa(RHASH_SIZE(hash));
    rb_hash_foreach(hash, to_a_i, ary);

    return ary;
}

Возвращает все элементы self в виде массива, состоящего из массивов по два элемента; каждый вложенный массив содержит пару ключ-значение из self:

h = {foo: 0, bar: 1, baz: 2}
h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]]

Связанные методы: см. Методы преобразования.

to_h {|key, value| ... } → new_hash Показать исходный код
to_h → self or new_hash
static VALUE
rb_hash_to_h(VALUE hash)
{
    if (rb_block_given_p()) {
        return rb_hash_to_h_block(hash);
    }
    if (rb_obj_class(hash) != rb_cHash) {
        const VALUE flags = RBASIC(hash)->flags;
        hash = hash_dup(hash, rb_cHash, flags & RHASH_PROC_DEFAULT);
    }
    return hash;
}

Если передан блок, возвращает новый хеш, содержимое которого формируется на основе блока; блок вызывается с ключом и значением каждой записи; блок должен возвращать массив из двух элементов, содержащий ключ и значение, которые будут включены в возвращаемый массив:

h = {foo: 0, bar: 1, baz: 2}
h.to_h {|key, value| [value, key] }
# => {0 => :foo, 1 => :bar, 2 => :baz}

Если блок не передан, возвращает self, если self является экземпляром Hash; если self является подклассом Hash, возвращает новый хеш, содержащий содержимое self.

Связанные методы: см. Методы преобразования.

to_hash → self Показать исходный код
static VALUE
rb_hash_to_hash(VALUE hash)
{
    return hash;
}

Возвращает self.

Связанные методы: см. Методы преобразования.

to_proc → proc Показать исходный код
static VALUE
rb_hash_to_proc(VALUE hash)
{
    return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
}

Возвращает объект Proc, который сопоставляет ключ его значению:

h = {foo: 0, bar: 1, baz: 2}
proc = h.to_proc
proc.class # => Proc
proc.call(:foo) # => 0
proc.call(:bar) # => 1
proc.call(:nosuch) # => nil

Связанные методы: см. Методы преобразования.

to_s
Псевдоним для: inspect
transform_keys {|old_key| ... } → new_hash Показать исходный код
transform_keys(other_hash) → new_hash
transform_keys(other_hash) {|old_key| ...} → new_hash
transform_keys → new_enumerator
static VALUE
rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
{
    VALUE result;
    struct transform_keys_args transarg = {0};

    argc = rb_check_arity(argc, 0, 1);
    if (argc > 0) {
        transarg.trans = to_hash(argv[0]);
        transarg.block_given = rb_block_given_p();
    }
    else {
        RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    }
    result = rb_hash_new();
    if (!RHASH_EMPTY_P(hash)) {
        if (transarg.trans) {
            transarg.result = result;
            rb_hash_foreach(hash, transform_keys_hash_i, (VALUE)&transarg);
        }
        else {
            rb_hash_foreach(hash, transform_keys_i, result);
        }
    }

    return result;
}

Если передан аргумент, блок или оба сразу, на основе self, аргумента и/или блока формирует новый хеш new_hash; все его ключи, некоторые из них или ни один могут отличаться от ключей в self.

Если передан блок, но не аргумент, ключи new_hash определяются только блоком.

Для каждой пары ключ-значение old_key/value в self вызывает блок с old_key; возвращаемое блоком значение становится new_key; задаёт new_hash[new_key] = value; повторяющийся ключ перезаписывает существующий:

h = {foo: 0, bar: 1, baz: 2}
h.transform_keys {|old_key| old_key.to_s }
# => {"foo" => 0, "bar" => 1, "baz" => 2}
h.transform_keys {|old_key| 'xxx' }
# => {"xxx" => 2}

Если передан аргумент other_hash, но не блок, в new_hash могут появиться новые ключи из other_hash и неизменённые ключи из self.

Для каждой пары ключ-значение old_key/old_value в self ищет ключ old_key в other_hash:

  • Если old_key найден, его значение other_hash[old_key] используется как new_key; задаёт new_hash[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO)
    # => {FOO: 0, BAR: 1, BAZ: 2}
    h.transform_keys(baz: :FOO, bar: :FOO, foo: :FOO)
    # => {FOO: 2}
    
  • Если old_key не найден, задаёт new_hash[old_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys({})
    # => {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :foo)
    # => {foo: 2, bar: 1}
    

Неиспользованные ключи в other_hash игнорируются:

h = {foo: 0, bar: 1, baz: 2}
h.transform_keys(bat: 3)
# => {foo: 0, bar: 1, baz: 2}

Если переданы и аргумент other_hash, и блок, новые ключи в new_hash задаются с помощью other_hash или блока, а неизменённые ключи берутся из self.

Для каждой пары old_key и value в self:

  • Если в other_hash есть ключ old_key (со значением new_key), блок для этого ключа не вызывается; задаёт new_hash[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
    # => {FOO: 0, BAR: 1, BAZ: 2}
    
  • Если в other_hash нет ключа old_key, вызывает блок с old_key и использует его возвращаемое значение как new_key; задаёт new_hash[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :BAZ) {|key| key.to_s.reverse }
    # => {"oof" => 0, "rab" => 1, BAZ: 2}
    h.transform_keys(baz: :BAZ) {|key| 'ook' }
    # => {"ook" => 1, BAZ: 2}
    

Если не переданы ни аргумент, ни блок, возвращает новый Enumerator.

Связанные методы: см. Методы преобразования ключей и значений.

transform_keys! {|old_key| ... } → self Показать исходный код
transform_keys!(other_hash) → self
transform_keys!(other_hash) {|old_key| ...} → self
transform_keys! → new_enumerator
static VALUE
rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
{
    VALUE trans = 0;
    int block_given = 0;

    argc = rb_check_arity(argc, 0, 1);
    if (argc > 0) {
        trans = to_hash(argv[0]);
        block_given = rb_block_given_p();
    }
    else {
        RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    }
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        long i;
        VALUE new_keys = hash_alloc(0);
        VALUE pairs = rb_ary_hidden_new(RHASH_SIZE(hash) * 2);
        rb_hash_foreach(hash, flatten_i, pairs);
        for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
            VALUE key = RARRAY_AREF(pairs, i), new_key, val;

            if (!trans) {
                new_key = rb_yield(key);
            }
            else if (!UNDEF_P(new_key = rb_hash_lookup2(trans, key, Qundef))) {
                /* use the transformed key */
            }
            else if (block_given) {
                new_key = rb_yield(key);
            }
            else {
                new_key = key;
            }
            val = RARRAY_AREF(pairs, i+1);
            if (!hash_stlike_lookup(new_keys, key, NULL)) {
                rb_hash_stlike_delete(hash, &key, NULL);
            }
            rb_hash_aset(hash, new_key, val);
            rb_hash_aset(new_keys, new_key, Qnil);
        }
        rb_ary_clear(pairs);
        rb_hash_clear(new_keys);
    }
    compact_after_delete(hash);
    return hash;
}

Если передан аргумент, блок или оба сразу, формирует ключи на основе аргумента, блока и self; все ключи в self, некоторые из них или ни один могут измениться.

Если передан блок, но не аргумент, формирует ключи только на основе блока; все ключи в self, некоторые из них или ни один могут измениться.

Для каждой пары ключ-значение old_key/value в self вызывает блок с old_key; возвращаемое блоком значение становится new_key; удаляет запись для old_key: self.delete(old_key); задаёт self[new_key] = value; повторяющийся ключ перезаписывает существующий:

h = {foo: 0, bar: 1, baz: 2}
h.transform_keys! {|old_key| old_key.to_s }
# => {"foo" => 0, "bar" => 1, "baz" => 2}
h = {foo: 0, bar: 1, baz: 2}
h.transform_keys! {|old_key| 'xxx' }
# => {"xxx" => 2}

Если передан аргумент other_hash, но не блок, формирует ключи для self на основе other_hash и self; все ключи в self, некоторые из них или ни один могут измениться.

Для каждой пары ключ-значение old_key/old_value в self ищет ключ old_key в other_hash:

  • Если old_key найден, использует значение other_hash[old_key] как new_key; удаляет запись для old_key: self.delete(old_key); задаёт self[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO)
    # => {FOO: 0, BAR: 1, BAZ: 2}
    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :FOO, bar: :FOO, foo: :FOO)
    # => {FOO: 2}
    
  • Если old_key не найден, ничего не делает:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!({})
    # => {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :foo)
    # => {foo: 2, bar: 1}
    

Неиспользованные ключи в other_hash игнорируются:

h = {foo: 0, bar: 1, baz: 2}
h.transform_keys!(bat: 3)
# => {foo: 0, bar: 1, baz: 2}

Если переданы и аргумент other_hash, и блок, формирует ключи на основе other_hash, блока и self; все ключи в self, некоторые из них или ни один могут измениться.

Для каждой пары old_key и value в self:

  • Если в other_hash есть ключ old_key (со значением new_key), блок для этого ключа не вызывается; удаляет запись для old_key: self.delete(old_key); задаёт self[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
    # => {FOO: 0, BAR: 1, BAZ: 2}
    
  • Если в other_hash нет ключа old_key, вызывает блок с old_key и использует его возвращаемое значение как new_key; удаляет запись для old_key: self.delete(old_key); задаёт self[new_key] = value; повторяющийся ключ перезаписывает существующий:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ) {|key| key.to_s.reverse }
    # => {"oof" => 0, "rab" => 1, BAZ: 2}
    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ) {|key| 'ook' }
    # => {"ook" => 1, BAZ: 2}
    

Если не переданы ни аргумент, ни блок, возвращает новый Enumerator.

Связанные методы: см. Методы преобразования ключей и значений.

transform_values {|value| ... } → new_hash Показать исходный код
transform_values → new_enumerator
static VALUE
rb_hash_transform_values(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = hash_dup_with_compare_by_id(hash);
    SET_DEFAULT(result, Qnil);

    if (!RHASH_EMPTY_P(hash)) {
        transform_values(result);
        compact_after_delete(result);
    }

    return result;
}

Если передан блок, возвращает новый хеш new_hash; для каждой пары key/value в self вызывает блок с value и сохраняет его результат как new_value; добавляет в new_hash запись key/new_value:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_values {|value| value * 100}
h1 # => {foo: 0, bar: 100, baz: 200}

Если блок не передан, возвращает новый Enumerator.

См. также: методы преобразования ключей и значений.

transform_values! {|old_value| ... } → self Показать исходный код
transform_values! → new_enumerator
static VALUE
rb_hash_transform_values_bang(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);

    if (!RHASH_TABLE_EMPTY_P(hash)) {
        transform_values(hash);
    }

    return hash;
}

Если передан блок, изменяет значения в self в соответствии с блоком; возвращает self.

Для каждой записи key/old_value в self вызывает блок с old_value, сохраняет его возвращаемое значение как new_value и устанавливает self[key] = new_value:

h = {foo: 0, bar: 1, baz: 2}
h.transform_values! {|value| value * 100} # => {foo: 0, bar: 100, baz: 200}

Если блок не передан, возвращает новый Enumerator.

См. также: методы преобразования ключей и значений.

update(*other_hashes) → self Показать исходный код
update(*other_hashes) { |key, old_value, new_value| ... } → self
static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
    struct update_call_args args = {
        .hash = self,
        .argv = argv,
        .argc = argc,
        .block_given = rb_block_given_p(),
        .iterating = false,
    };
    VALUE arg = (VALUE)&args;

    rb_hash_modify(self);
    return rb_ensure(rb_hash_update_call, arg, rb_hash_update_ensure, arg);
}

Обновляет значения и/или добавляет записи в self; возвращает self.

Каждый аргумент other_hash в other_hashes должен быть хешем.

Если блок не передан, для каждой последующей записи key/new_value в каждом последующем other_hash:

  • Если key содержится в self, устанавливает self[key] = new_value, сохраняя исходную позицию:

    h0 = {foo: 0, bar: 1, baz: 2}
    h1 = {bar: 3, foo: -1}
    h0.update(h1) # => {foo: -1, bar: 3, baz: 2}
    
  • Если key не содержится в self, добавляет запись в конец self:

    h = {foo: 0, bar: 1, baz: 2}
    h.update({bam: 3, bah: 4}) # => {foo: 0, bar: 1, baz: 2, bam: 3, bah: 4}
    

Если передан блок, для каждой последующей записи key/new_value в каждом последующем other_hash:

  • Если key содержится в self, получает old_value из self[key], вызывает блок с key, old_value и new_value, а затем устанавливает self[key] = new_value, сохраняя исходную позицию:

    season = {AB: 75, H: 20, HR: 3, SO: 17, W: 11, HBP: 3}
    today = {AB: 3, H: 1, W: 1}
    yesterday = {AB: 4, H: 2, HR: 1}
    season.update(yesterday, today) {|key, old_value, new_value| old_value + new_value }
    # => {AB: 82, H: 23, HR: 4, SO: 17, W: 12, HBP: 3}
    
  • Если key не содержится в self, добавляет запись в конец self:

    h = {foo: 0, bar: 1, baz: 2}
    h.update({bat: 3}) { fail 'Cannot happen' }
    # => {foo: 0, bar: 1, baz: 2, bat: 3}
    

См. также: методы присваивания.

Также имеет псевдоним: merge!
value?
Псевдоним для: has_value?
values → new_array Показать исходный код
VALUE
rb_hash_values(VALUE hash)
{
    VALUE values;
    st_index_t size = RHASH_SIZE(hash);

    values = rb_ary_new_capa(size);
    if (size == 0) return values;

    if (ST_DATA_COMPATIBLE_P(VALUE)) {
        if (RHASH_AR_TABLE_P(hash)) {
            rb_gc_writebarrier_remember(values);
            RARRAY_PTR_USE(values, ptr, {
                size = ar_values(hash, ptr, size);
            });
        }
        else if (RHASH_ST_TABLE_P(hash)) {
            st_table *table = RHASH_ST_TABLE(hash);
            rb_gc_writebarrier_remember(values);
            RARRAY_PTR_USE(values, ptr, {
                size = st_values(table, ptr, size);
            });
        }
        rb_ary_set_len(values, size);
    }
    else {
        rb_hash_foreach(hash, values_i, values);
    }

    return values;
}

Возвращает новый массив, содержащий все значения из self:

h = {foo: 0, bar: 1, baz: 2}
h.values # => [0, 1, 2]

См. также: методы получения данных.

values_at(*keys) → new_array Показать исходный код
static VALUE
rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
{
    VALUE result = rb_ary_new2(argc);
    long i;

    for (i=0; i<argc; i++) {
        rb_ary_push(result, rb_hash_aref(hash, argv[i]));
    }
    return result;
}

Возвращает новый массив, содержащий значения для указанных keys:

h = {foo: 0, bar: 1, baz: 2}
h.values_at(:baz, :foo) # => [2, 0]

Для каждого ненайденного ключа возвращается значение хеша по умолчанию:

h.values_at(:hello, :foo) # => [nil, 0]

См. также: методы получения данных.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API