Spec-Zone.ru › Ruby 3.4

класс Hash

Родитель:
Объект
Включенные модули:
Enumerable

A Hash сопоставляет каждый из своих уникальных ключей со специфическим значением.

A Hash имеет определенное сходство с Array, но:

  • У Array индекс всегда является Integer.

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

Hash Синтаксис данных

Старый синтаксис для Hash данных использует «стрелку хэша», =>:

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

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

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

Вы также можете использовать String вместо простого слова:

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'}

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

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

Общие применения

Вы можете использовать Hash для присвоения имен объектам:

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

Вы можете использовать Hash для присвоения имен аргументам метода:

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

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

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

Вы можете использовать Hash для инициализации объекта:

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

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

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

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

  • Метода Hash.

Вы можете создать Hash, вызвав метод Hash.new.

Создать пустой Hash:

h = Hash.new
h # => {}
h.class # => Hash

Вы можете создать Hash, вызвав метод Hash.[].

Создать пустой Hash:

h = Hash[]
h # => {}

Создать Hash с начальными записями:

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

Вы можете создать Hash, используя его литеральную форму (фигурные скобки).

Создать пустой Hash:

h = {}
h # => {}

Создать Hash с начальными записями:

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

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

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

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

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

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}

Самый простой способ удалить запись Hash (метод экземпляра 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.

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

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

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

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

Методы [], values_at и dig должны возвращать значение, связанное с определенным ключом. Если такой ключ не найден, это значение будет определяться его функцией по умолчанию (если она есть) или же значением по умолчанию (по умолчанию «nil»).

Вы можете получить значение по умолчанию с помощью метода default:

h = Hash.new
h.default # => nil

Вы можете установить значение по умолчанию, передав аргумент методу Hash.new или с помощью метода default=

h = Hash.new(-1)
h.default # => -1
h.default = 0
h.default # => 0

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

counts = {foo: 42}
counts.default # => nil (default)
counts[:foo] = 42
counts[:bar] # => nil
counts.default = 0
counts[:bar] # => 0
counts.values_at(:foo, :bar, :baz) # => [42, 0, 0]
counts.dig(:bar) # => 0

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

synonyms = Hash.new([])
synonyms[:hello] # => []
synonyms[:hello] << :hi # => [:hi], but this mutates the default!
synonyms.default # => [:hi]
synonyms[:world] << :universe
synonyms[:world] # => [:hi, :universe], oops
synonyms.keys # => [], oops

Для использования изменяемого объекта в качестве значения по умолчанию рекомендуется использовать функцию по умолчанию

Функция по умолчанию Proc

Когда функция по умолчанию для Hash установлена (т. е., не nil), значение по умолчанию, возвращаемое методом [], определяется только функцией по умолчанию.

Вы можете получить функцию по умолчанию с помощью метода default_proc:

h = Hash.new
h.default_proc # => nil

Вы можете установить функцию по умолчанию, вызвав Hash.new с блоком или вызвав метод default_proc=

h = Hash.new { |hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
h.default_proc = proc { |hash, key| "Default value for #{key.inspect}" }
h.default_proc.class # => Proc

Когда функция по умолчанию установлена (т. е., не nil) и вызван метод [] с несуществующим ключом, [] вызывает функцию по умолчанию с объектом Hash и отсутствующим ключом, а затем возвращает возвращаемое значение функции:

h = Hash.new { |hash, key| "Default value for #{key}" }
h[:nosuch] # => "Default value for nosuch"

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

h.include?(:nosuch) # => false

Однако сама функция может добавить новую запись:

synonyms = Hash.new { |hash, key| hash[key] = [] }
synonyms.include?(:hello) # => false
synonyms[:hello] << :hi # => [:hi]
synonyms[:world] << :universe # => [:universe]
synonyms.keys # => [:hello, :world]

Обратите внимание, что установка функции по умолчанию очищает значение по умолчанию и наоборот.

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

Что здесь

Прежде всего, что есть в другом месте. Класс Hash:

  • Унаследован от класса Объект.

  • Включает модуль 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!: Удаляет все записи со значением nil из self.

  • 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: Вызывает заданный блок для каждого значения.

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

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

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

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

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

  • to_proc: Возвращает proc, который отображает заданный ключ на его значение.

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

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

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

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

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

Другие методы

  • flatten: Возвращает массив, являющийся 1-мерным развёртыванием self.

  • invert: Возвращает хэш с каждой парой ключ-значение, инвертированной.

Методы публичного класса

Hash[] → new_empty_hash
Hash[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.

Без аргумента возвращает новый пустой Hash.

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

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

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

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

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

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

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

new(default_value = nil) → new_hash
new(default_value = nil, capacity: size) → new_hash
new {|hash, key| ... } → new_hash
new(capacity: size) {|hash, 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.

Начальное значение по умолчанию и начальная процедура по умолчанию для нового хэша зависят от того, какая форма использовалась выше. См. Значения по умолчанию.

Если не указан ни аргумент, ни блок, инициализирует значение по умолчанию и процедуру по умолчанию к nil:

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

Если аргумент default_value указан, но блок нет, инициализирует значение по умолчанию заданным default_value и процедуру по умолчанию к nil:

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

Если блок указан, но не default_value, сохраняет блок в качестве процедуры по умолчанию и устанавливает значение по умолчанию к nil:

h = Hash.new {|hash, key| "Default value for #{key}" }
h.default # => nil
h.default_proc.class # => Proc
h[:nosuch] # => "Default value for nosuch"

Если указаны и блок, и default_value, выбрасывает ArgumentError.

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

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(obj) → obj, new_hash, or nil
Исходный код
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
    return rb_check_hash_type(hash);
}

Если obj является объектом Hash, возвращает obj.

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

Возвращает nil если obj не отвечает на :to_hash

Вызывает исключение, если obj.to_hash не возвращает объект Hash.

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

hash < other_hash → true или 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);
}

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

false
hash <= other_hash → true или 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);
}

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

false
hash == object → true или false
Исходный код
static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}

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

  • object является объектом Hash.

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

  • Для каждого ключа key, hash[key] == object[key].

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

Равность:

h1 = {foo: 0, bar: 1, baz: 2}
h2 = {foo: 0, bar: 1, baz: 2}
h1 == h2 # => true
h3 = {baz: 2, bar: 1, foo: 0}
h1 == h3 # => true
hash > other_hash → true или 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, если hash является собственным надмножеством other_hash, и false в противном случае:

false
hash >= other_hash → true или 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, если hash является надмножеством other_hash, и false в противном случае:

false
hash[key] → value
Исходный код
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);
    }
}

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

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

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

h = {foo: 0, bar: 1, baz: 2}
h[:nosuch] # => nil
hash[key] = value → value
Исходный код
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;
}

Связывает заданное значение с заданным ключом; возвращает заданное значение.

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

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

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

h = {foo: 0, bar: 1}
h[:baz] = 2 # => 2
h.store(:bat, 3) # => 3
h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
Также алиас: store
any? → true или false
any?(object) → true или false
any? {|key, value| ... } → true или 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 нет элементов, возвращает true, и аргумент или блок не используются.

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

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

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

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

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

См. также: Enumerable#any?

assoc(key) → new_array или 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];
}

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

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

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

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.

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}
h1 = h.compact
h1 # => {:foo=>0, :baz=>2}
compact! → self или 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 (на месте):

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

Возвращает 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.

По умолчанию, эти два объекта считаются одним и тем же ключом, поэтому s1 перезапишет s0:

s0 = 'x'
s1 = 'x'
h = {}
h.compare_by_identity? # => false
h[s0] = 0
h[s1] = 1
h # => {"x"=>1}

После вызова #compare_by_identity ключи считаются разными, и поэтому не перезаписывают друг друга:

h = {}
h.compare_by_identity # => {}
h.compare_by_identity? # => true
h[s0] = 0
h[s1] = 1
h # => {"x"=>0, "x"=>1}
compare_by_identity? → true or false
Source
VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    return RBOOL(RHASH_IDENTHASH_P(hash));
}

Возвращает true если compare_by_identity был вызван, false иначе.

default → object
default(key) → object
Source
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
Source
static 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
Source
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
Source
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
Source
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 и возвращает его связанное значение.

Если блок не задан и 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
Source
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}

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

h = {foo: 0, bar: 1, baz: 2}
e = h.delete_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:delete_if>
e.each { |key, value| value > 0 } # => {:foo=>0}
dig(key, *identifiers) → object
Source
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 Methods.

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

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) # => h
h.dig(:hello, :world, :foo, :bar, 2) # => :c
each {|key, value| ... } → self
each → new_enumerator

Вызывает заданный блок с каждой парой ключ-значение; возвращает 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 если блок не задан:

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

Вывод:

foo: 0
bar: 1
baz: 2
Псевдоним для: each_pair
each_key {|key| ... } → self
each_key → new_enumerator
Source
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 если блок не задан:

h = {foo: 0, bar: 1, baz: 2}
e = h.each_key # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_key>
h1 = e.each {|key| puts key }
h1 # => {:foo=>0, :bar=>1, :baz=>2}

Вывод:

foo
bar
baz
each_pair {|key, value| ... } → self
each_pair → new_enumerator
Source
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 если блок не задан:

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

Вывод:

foo: 0
bar: 1
baz: 2
Также имеет псевдоним: each
each_value {|value| ... } → self
each_value → new_enumerator
Source
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 если блок не задан:

h = {foo: 0, bar: 1, baz: 2}
e = h.each_value # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_value>
h1 = e.each {|value| puts value }
h1 # => {:foo=>0, :bar=>1, :baz=>2}

Вывод:

0
1
2
empty? → true or false
Source
VALUE
rb_hash_empty_p(VALUE hash)
{
    return RBOOL(RHASH_EMPTY_P(hash));
}

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

{}.empty? # => true
{foo: 0, bar: 1, baz: 2}.empty? # => false
eql?(object) → true or false
Source
static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}

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

  • object является объектом Hash.

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

  • Для каждого ключа key, h[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) → a_hash
Source
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;
}

Возвращает новый Hash без записей для заданных keys:

h = { a: 100, b: 200, c: 300 }
h.except(:a)          #=> {:b=>200, :c=>300}

Любые заданные keys, которые не найдены, игнорируются.

fetch(key) → object
fetch(key, default_value) → object
fetch(key) {|key| ... } → object
Source
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

Если key не найден и блок не был задан, возвращает default_value:

{}.fetch(:nosuch, :default) # => :default

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

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

Вызывает исключение KeyError, если не был задан ни default_value, ни блок.

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

fetch_values(*keys) → new_array
fetch_values(*keys) {|key| ... } → new_array
Source
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;
}

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

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

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

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

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

Когда блок не задан, вызывает исключение, если какой-либо заданный ключ не найден.

filter
Псевдоним для: select
filter!
Псевдоним для: select!
flatten → new_array
flatten(level) → new_array
Source
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;
}

Возвращает новый объект Array, представляющий собой одномерное сглаживание self.

По умолчанию, вложенные массивы не сглаживаются:

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

Принимает глубину рекурсивного сглаживания из аргумента Integer level:

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

Когда level отрицателен, сглаживает все вложенные массивы:

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

Когда level равен нулю, возвращает эквивалент to_a:

h = {foo: 0, bar: [:bat, 3], baz: 2}
h.flatten(0) # => [[:foo, 0], [:bar, [:bat, 3]], [:baz, 2]]
h.flatten(0) == h.to_a # => true
has_key?(key) → true or false

Возвращает true, если key является ключом в self, в противном случае false.

Псевдоним для: include?
has_value?(value) → true or false
Source
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];
}

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

Также является псевдонимом для: value?
hash → an_integer
Source
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);
}

Возвращает Integer хэш-код для хеша.

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

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
Source
VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

Возвращает true, если key является ключом в self, в противном случае false.

Также является псевдонимом для: member?, has_key?, key?
initialize_copy
Source
Также является псевдонимом для: replace
inspect → new_string
Source
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);
}

Возвращает новый String содержащий записи хеша:

h = {foo: 0, bar: 1, baz: 2}
h.inspect # => "{foo: 0, bar: 1, baz: 2}"
Также является псевдонимом для: to_s
invert → новый_хэш
Исходный код
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;
}

Возвращает новый объект Hash с инвертированными парами ключ-значение:

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 {|ключ, значение| ... } → self
keep_if → новый_перечислитель
Исходный код
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, если блок не задан:

h = {foo: 0, bar: 1, baz: 2}
e = h.keep_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:keep_if>
e.each { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2}
key(значение) → ключ или 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?(ключ) → true или false

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

Псевдоним для: include?
keys → новый_массив
Исходный код
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;
}

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

h = {foo: 0, bar: 1, baz: 2}
h.keys # => [:foo, :bar, :baz]
length → целое число

Возвращает количество элементов в self:

{foo: 0, bar: 1, baz: 2}.length # => 3
Псевдоним для: size
member?(ключ) → true или false

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

Псевдоним для: include?
merge → копия_себя
merge(*другие_хэши) → новый_хэш
merge(*другие_хэши) { |ключ, старое_значение, новое_значение| ... } → новый_хэш
Исходный код
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));
}

Возвращает новый Hash, образованный слиянием каждого из other_hashes в копию self.

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

С аргументами и без блока:

  • Возвращает новый Hash объект, образованный слиянием каждого последующего Hash в other_hashes в 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}

С аргументами и блоком:

  • Возвращает новый Hash объект, являющийся результатом слияния self и каждого заданного хэша.

  • Заданные хэши сливаются слева направо.

  • Каждый новый элемент добавляется в конец.

  • Для каждого дублирующегося ключа:

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

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

Пример:

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

Без аргументов:

  • Возвращает копию self.

  • Блок, если задан, игнорируется.

Пример:

h = {foo: 0, bar: 1, baz: 2}
h.merge # => {:foo=>0, :bar=>1, :baz=>2}
h1 = h.merge { |key, old_value, new_value| raise 'Cannot happen' }
h1 # => {:foo=>0, :bar=>1, :baz=>2}
merge! → self
merge!(*другие_хэши) → self
merge!(*другие_хэши) { |ключ, старое_значение, новое_значение| ... } → self

Сливает каждый из other_hashes в self; возвращает self.

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

С аргументами и без блока:

  • Возвращает 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}

С аргументами и блоком:

  • Возвращает self, после слияния заданных хэшей.

  • Заданные хэши сливаются слева направо.

  • Каждый новый элемент добавляется в конец.

  • Для каждого дублирующегося ключа:

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

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

Пример:

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

Без аргументов:

  • Возвращает self, без изменений.

  • Блок, если задан, игнорируется.

Пример:

h = {foo: 0, bar: 1, baz: 2}
h.merge # => {:foo=>0, :bar=>1, :baz=>2}
h1 = h.merge! { |key, old_value, new_value| raise 'Cannot happen' }
h1 # => {:foo=>0, :bar=>1, :baz=>2}
Псевдоним для: update
rassoc(значение) → новый_массив или 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];
}

Возвращает новый 2-элементный Array, состоящий из ключа и значения первого найденного элемента, значение которого равно == значению (см. Порядок элементов):

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

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

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.

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

END_OF_DOCUMENT_MARKER
reject {|ключ, значение| ... } → новый_хэш
reject → новый_перечислитель
Исходный код
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;
}

Возвращает новый объект Hash, чьи записи — это все те записи из self, для которых блок возвращает false или nil;

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

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

h = {foo: 0, bar: 1, baz: 2}
e = h.reject # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject>
h1 = e.each {|key, value| key.start_with?('b') }
h1 # => {:foo=>0}
reject! {|ключ, значение| ... } → self или null
reject! → новый_перечислитель
Исходный код
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, чьи оставшиеся записи — это те записи, для которых блок возвращает false или nil:

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

Возвращает nil, если ни одна запись не была удалена.

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

h = {foo: 0, bar: 1, baz: 2}
e = h.reject! # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject!>
e.each {|key, value| key.start_with?('b') } # => {:foo=>0}
replace(другой_хэш) → self

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

h = {foo: 0, bar: 1, baz: 2}
h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4}
Псевдоним для: initialize_copy
select {|ключ, значение| ... } → новый_хэш
select → новый_перечислитель
Исходный код
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;
}

Возвращает новый объект Hash, чьи записи — это те записи, для которых блок возвращает истинное значение:

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

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

h = {foo: 0, bar: 1, baz: 2}
e = h.select # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select>
e.each {|key, value| value < 2 } # => {:foo=>0, :bar=>1}
Также алиас для: filter
select! {|ключ, значение| ... } → self или null
select! → новый_перечислитель
Исходный код
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, чьи записи — это те записи, для которых блок возвращает истинное значение:

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

Возвращает nil если ни одна запись не была удалена.

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

h = {foo: 0, bar: 1, baz: 2}
e = h.select!  # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select!>
e.each { |key, value| value < 2 } # => {:foo=>0, :bar=>1}
Также алиас для: filter!
shift → [ключ, значение] или null
Исходный код
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;
}

Удаляет первую запись хэша (см. Порядок записей); возвращает 2-элементный массив Array, содержащий удалённый ключ и значение:

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

Возвращает null, если хэш пуст.

size → целое
Исходный код
VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}

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

{foo: 0, bar: 1, baz: 2}.length # => 3
Также алиас для: length
slice(*ключи) → новый_хэш
Исходный код
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;
}

Возвращает новый объект Hash, содержащий записи для заданных keys:

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

Любые заданные keys которые не найдены, игнорируются.

store(ключ, значение)

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

Если данный key существует, заменяет его значение на заданное value; порядок не затрагивается (см. Порядок записей):

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

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

h = {foo: 0, bar: 1}
h[:baz] = 2 # => 2
h.store(:bat, 3) # => 3
h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
Псевдоним для: []=
to_a → новый_массив
Исходный код
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;
}

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

h = {foo: 0, bar: 1, baz: 2}
h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
to_h → self или новый_хэш
to_h {|ключ, значение| ... } → новый_хэш
Исходный код
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;
}

Для экземпляра Hash, возвращает self.

Для подкласса Hash, возвращает новый Hash, содержащий содержимое self.

Когда задан блок, возвращает новый объект Hash, чьё содержимое основано на блоке; блок должен возвращать объект массива Array из 2 элементов, определяющий пару ключ-значение, которая будет включена в возвращённый массив:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.to_h {|key, value| [value, key] }
h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
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
END_OF_DOCUMENT_MARKER
transform_keys {|ключ| ... } → новый_хеш
transform_keys(хеш2) → новый_хеш
transform_keys(хеш2) {|другой_ключ| ...} → новый_хеш
transform_keys → новый_перечислитель
Исходный код
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;
}

Возвращает новый объект Hash; каждая запись имеет:

  • Ключ, заданный блоком.

  • Значение из self.

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

Преобразование ключей:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_keys {|key| key.to_s }
h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}

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

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

Перезаписывает значения для дублирующих ключей:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_keys {|key| :bat }
h1 # => {:bat=>2}

Возвращает новый Enumerator, если блок не указан:

h = {foo: 0, bar: 1, baz: 2}
e = h.transform_keys # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_keys>
h1 = e.each { |key| key.to_s }
h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}
transform_keys! {|ключ| ... } → self
transform_keys!(хеш2) → self
transform_keys!(хеш2) {|другой_ключ| ...} → self
transform_keys! → новый_перечислитель
Исходный код
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;
}

То же самое, что и Hash#transform_keys, но изменяет получатель на месте вместо возвращения нового хеша.

transform_values {|значение| ... } → новый_хеш
transform_values → новый_перечислитель
Исходный код
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)) {
        rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, result);
        compact_after_delete(result);
    }

    return result;
}

Возвращает новый объект Hash; каждая запись имеет:

  • Ключ из self.

  • Значение, заданное блоком.

Преобразование значений:

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

Возвращает новый Enumerator, если блок не указан:

h = {foo: 0, bar: 1, baz: 2}
e = h.transform_values # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_values>
h1 = e.each { |value| value * 100}
h1 # => {:foo=>0, :bar=>100, :baz=>200}
transform_values! {|значение| ... } → self
transform_values! → новый_перечислитель
Исходный код
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)) {
        rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
    }

    return hash;
}

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

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

Возвращает новый Enumerator если блок не указан:

h = {foo: 0, bar: 1, baz: 2}
e = h.transform_values! # => #<Enumerator: {:foo=>0, :bar=>100, :baz=>200}:transform_values!>
h1 = e.each {|value| value * 100}
h1 # => {:foo=>0, :bar=>100, :baz=>200}
update
Исходный код
Также алиас для: merge!
value?(значение) → true или false

Возвращает true если value — значение в self, в противном случае false.

Псевдоним для: has_value?
values → новый_массив
Исходный код
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;
}

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

h = {foo: 0, bar: 1, baz: 2}
h.values # => [0, 1, 2]
values_at(*ключи) → новый_массив
Исходный код
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;
}

Возвращает новый Array, содержащий значения для заданных 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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