Spec-Zone.ru › Ruby 2.7

класс Hash

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

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

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

Словарь можно легко создать, используя его неявную форму:

grades = { "Jane Doe" => 10, "Jim Doe" => 6 }

Словари позволяют использовать альтернативный синтаксис для ключей, которые являются символами. Вместо

options = { :font_size => 10, :font_family => "Arial" }

Вы можете написать это как:

options = { font_size: 10, font_family: "Arial" }

Каждый именованный ключ — это символ, к которому вы можете получить доступ в словаре:

options[:font_size]  # => 10

Словарь также можно создать с помощью своего метода ::new:

grades = Hash.new
grades["Dorothy Doe"] = 9

У словаря есть значение по умолчанию, которое возвращается при обращении к ключам, которые не существуют в словаре. Если значение по умолчанию не задано, используется nil. Вы можете установить значение по умолчанию, передав его в качестве аргумента методу Hash.new:

grades = Hash.new(0)

Или с помощью метода default=:

grades = {"Timmy Doe" => 8}
grades.default = 0

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

puts grades["Jane Doe"] # => 0

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

Словари — это простой способ представления структур данных, таких как

books         = {}
books[:matz]  = "The Ruby Programming Language"
books[:black] = "The Well-Grounded Rubyist"

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

Person.create(name: "John Doe", age: 27)

def self.create(params)
  @name = params[:name]
  @age  = params[:age]
end

Hash Ключи словаря

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

Пользовательский класс может использоваться в качестве ключа словаря, если методы hash и eql? переопределены для предоставления осмысленного поведения. По умолчанию отдельные экземпляры ссылаются на отдельные ключи словаря.

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

class Book
  attr_reader :author, :title

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

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

  alias eql? ==

  def hash
    @author.hash ^ @title.hash # XOR
  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

См. также Object#hash и Object#eql?

Публичные методы класса

Hash[ key, value, ... ] → new_hash Показать исходный код
Hash[ [ [key, value], ... ] ] → new_hash
Hash[ object ] → 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)) {
            hash = hash_alloc(klass);
            if (RHASH_AR_TABLE_P(tmp)) {
                ar_copy(hash, tmp);
            }
            else {
                RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(tmp)));
            }
            return hash;
        }

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

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

Аналогично литералу { key => value, ... }. В первой форме ключи и значения встречаются парами, поэтому должно быть чётное количество аргументов.

Во второй и третьей форме принимается единственный аргумент, который является либо массивом пар ключ-значение, либо объектом, преобразуемым в словарь.

Hash["a", 100, "b", 200]             #=> {"a"=>100, "b"=>200}
Hash[ [ ["a", 100], ["b", 200] ] ]   #=> {"a"=>100, "b"=>200}
Hash["a" => 100, "b" => 200]         #=> {"a"=>100, "b"=>200}
new → new_hash Показать исходный код
new(obj) → new_hash
new {|hash, key| block } → new_hash
static VALUE
rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
{
    VALUE ifnone;

    rb_hash_modify(hash);
    if (rb_block_given_p()) {
        rb_check_arity(argc, 0, 0);
        ifnone = rb_block_proc();
        SET_PROC_DEFAULT(hash, ifnone);
    }
    else {
        rb_check_arity(argc, 0, 1);
        ifnone = argc == 0 ? Qnil : argv[0];
        RHASH_SET_IFNONE(hash, ifnone);
    }

    return hash;
}

Возвращает новый пустой словарь. Если к этому словарю впоследствии обращаются по ключу, который не соответствует записи в словаре, возвращаемое значение зависит от стиля new , используемого для создания словаря. В первой форме обращение возвращает nil. Если указан объект, этот единственный объект будет использоваться для всех значений по умолчанию. Если указан блок, он будет вызываться с объектом словаря и ключом и должен возвращать значение по умолчанию. Блок несет ответственность за сохранение значения в словаре, если это необходимо.

h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"]           #=> 100
h["c"]           #=> "Go Fish"
# The following alters the single default object
h["c"].upcase!   #=> "GO FISH"
h["d"]           #=> "GO FISH"
h.keys           #=> ["a", "b"]

# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"]           #=> "Go Fish: c"
h["c"].upcase!   #=> "GO FISH: C"
h["d"]           #=> "Go Fish: d"
h.keys           #=> ["c", "d"]
ruby2_keywords_hash(hash) → hash Показать исходный код
static VALUE
rb_hash_s_ruby2_keywords_hash(VALUE dummy, VALUE hash)
{
    Check_Type(hash, T_HASH);
    hash = rb_hash_dup(hash);
    RHASH(hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
    return hash;
}

Создаёт копию заданного словаря и добавляет флаг 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 (RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS) ? Qtrue : Qfalse;
}

Проверяет, помечен ли заданный словарь методом 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) → hash or nil Показать исходный код
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
    return rb_check_hash_type(hash);
}

Попытка преобразовать объект в словарь, используя метод to_hash. Возвращает преобразованный словарь или nil, если объект не может быть преобразован по какой-либо причине.

Hash.try_convert({1=>2})   # => {1=>2}
Hash.try_convert("1=>2")   # => nil

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

hash < other → 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.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 < h2    #=> true
h2 < h1    #=> false
h1 < h1    #=> false
hash <= other → 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 или равно other.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 <= h2   #=> true
h2 <= h1   #=> false
h1 <= h1   #=> true
hsh == other_hash → true или false Показать исходный код
static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}

Равенство — Два хэша равны, если они содержат одинаковое количество ключей и если каждая пара «ключ-значение» равна (в соответствии с Object#==) соответствующим элементам в другом хэше.

h1 = { "a" => 1, "c" => 2 }
h2 = { 7 => 35, "c" => 2, "a" => 1 }
h3 = { "a" => 1, "c" => 2, 7 => 35 }
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h1 == h2   #=> false
h2 == h3   #=> true
h3 == h4   #=> false

Порядок элементов хэшей не сравнивается.

h1 = { "a" => 1, "c" => 2 }
h2 = { "c" => 2, "a" => 1 }
h1 == h2   #=> true
hash > other → 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 , если other является подмножеством hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 > h2    #=> false
h2 > h1    #=> true
h1 > h1    #=> false
hash >= other → 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 , если other является подмножеством hash или равно hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 >= h2   #=> false
h2 >= h1   #=> true
h1 >= h1   #=> true
hsh[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);
    }
}

Обращение к элементу — Возвращает объект value, соответствующий объекту key. Если не найдено, возвращает значение по умолчанию (см. Hash::new для подробностей).

h = { "a" => 100, "b" => 200 }
h["a"]   #=> 100
h["c"]   #=> nil
hsh[key] = value → value Показать исходный код
VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    int iter_lev = RHASH_ITER_LEV(hash);

    rb_hash_modify(hash);

    if (RHASH_TABLE_NULL_P(hash)) {
        if (iter_lev > 0) no_new_key();
        ar_alloc_table(hash);
    }

    if (RHASH_TYPE(hash) == &identhash || rb_obj_class(key) != rb_cString) {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
    }
    else {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
    }
    return val;
}

Присвоение элемента

Связывает значение, заданное value , с ключом, заданным key .

h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h   #=> {"a"=>9, "b"=>200, "c"=>4}
h.store("d", 42) #=> 42
h   #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}

key не должен изменять своего значения во время использования в качестве ключа (ключ, представленный как unfrozen String , будет дублирован и заморожен).

a = "a"
b = "b".freeze
h = { a => 100, b => 200 }
h.key(100).equal? a #=> false
h.key(200).equal? b #=> true
any? [{ |(key, value)| block }] → true или false Показать исходный код
any?(pattern) → 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_arity() > 1)
            rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
        else
            rb_hash_foreach(hash, any_p_i, (VALUE)args);
    }
    return args[0];
}

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

assoc(obj) → массив или nil Показать исходный код
VALUE
rb_hash_assoc(VALUE hash, VALUE key)
{
    st_table *table;
    const struct st_hash_type *orighash;
    VALUE args[2];

    if (RHASH_EMPTY_P(hash)) return Qnil;

    ar_force_convert_table(hash, __FILE__, __LINE__);
    HASH_ASSERT(RHASH_ST_TABLE_P(hash));
    table = RHASH_ST_TABLE(hash);
    orighash = table->type;

    if (orighash != &identhash) {
        VALUE value;
        struct reset_hash_type_arg ensure_arg;
        struct st_hash_type assochash;

        assochash.compare = assoc_cmp;
        assochash.hash = orighash->hash;
        table->type = &assochash;
        args[0] = hash;
        args[1] = key;
        ensure_arg.hash = hash;
        ensure_arg.orighash = orighash;
        value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
        if (value != Qundef) return rb_assoc_new(key, value);
    }

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

Ищет в хэше, сравнивая obj с ключом с использованием ==. Возвращает пару «ключ-значение» (массив из двух элементов) или nil , если совпадение не найдено. См. Array#assoc.

h = {"colors"  => ["red", "blue", "green"],
     "letters" => ["a", "b", "c" ]}
h.assoc("letters")  #=> ["letters", ["a", "b", "c"]]
h.assoc("foo")      #=> nil
clear → hsh Показать исходный код
VALUE
rb_hash_clear(VALUE hash)
{
    rb_hash_modify_check(hash);

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

    return hash;
}

Удаляет все пары «ключ-значение» из hsh.

h = { "a" => 100, "b" => 200 }   #=> {"a"=>100, "b"=>200}
h.clear                          #=> {}
compact → new_hash Показать исходный код
static VALUE
rb_hash_compact(VALUE hash)
{
    VALUE result = rb_hash_new();
    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_foreach(hash, set_if_not_nil, result);
    }
    return result;
}

Возвращает новый хэш со удаленными парами/значениями nil.

h = { a: 1, b: false, c: nil }
h.compact     #=> { a: 1, b: false }
h             #=> { a: 1, b: false, c: nil }
compact! → hsh или 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;
}

Удаляет все значения nil из хэша. Возвращает nil, если изменений не было, иначе возвращает хэш.

h = { a: 1, b: false, c: nil }
h.compact!     #=> { a: 1, b: false }
compare_by_identity → hsh Показать исходный код
static 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);
    ar_force_convert_table(hash, __FILE__, __LINE__);
    HASH_ASSERT(RHASH_ST_TABLE_P(hash));

    tmp = hash_alloc(0);
    identtable = rb_init_identtable_with_size(RHASH_SIZE(hash));
    RHASH_ST_TABLE_SET(tmp, identtable);
    rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
    st_free_table(RHASH_ST_TABLE(hash));
    RHASH_ST_TABLE_SET(hash, identtable);
    RHASH_ST_CLEAR(tmp);
    rb_gc_force_recycle(tmp);

    return hash;
}

Заставляет hsh сравнивать ключи по их идентичности, то есть будет считать абсолютно одинаковые объекты одинаковыми ключами.

h1 = { "a" => 100, "b" => 200, :c => "c" }
h1["a"]        #=> 100
h1.compare_by_identity
h1.compare_by_identity? #=> true
h1["a".dup]    #=> nil  # different objects.
h1[:c]         #=> "c"  # same symbols are all same.
compare_by_identity? → true или false Показать исходный код
MJIT_FUNC_EXPORTED VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    if (RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}

Возвращает true , если hsh сравнивает ключи по их идентичности. Также см. Hash#compare_by_identity.

deconstruct_keys(p1) Показать исходный код
static VALUE
rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
{
    return hash;
}
default(key=nil) → obj Показать исходный код
static VALUE
rb_hash_default(int argc, VALUE *argv, VALUE hash)
{
    VALUE args[2], ifnone;

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

Возвращает значение по умолчанию, значение, которое вернул бы hsh, если key не существует в hsh. Также см. Hash::new и Hash#default=.

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

h = Hash.new("cat")                     #=> {}
h.default                               #=> "cat"
h.default(2)                            #=> "cat"

h = Hash.new {|h,k| h[k] = k.to_i*10}   #=> {}
h.default                               #=> nil
h.default(2)                            #=> 20
default = obj → obj Показать исходный код
static VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
    rb_hash_modify_check(hash);
    SET_DEFAULT(hash, ifnone);
    return ifnone;
}

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

h = { "a" => 100, "b" => 200 }
h.default = "Go fish"
h["a"]     #=> 100
h["z"]     #=> "Go fish"
# This doesn't do what you might hope...
h.default = proc do |hash, key|
  hash[key] = key + key
end
h[2]       #=> #<Proc:0x401b3948@-:6>
h["cat"]   #=> #<Proc:0x401b3948@-:6>
default_proc → объект Показать исходный код
static VALUE
rb_hash_default_proc(VALUE hash)
{
    if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
        return RHASH_IFNONE(hash);
    }
    return Qnil;
}

Если Hash::new был вызван с блоком, верните этот блок, иначе верните nil.

h = Hash.new {|h,k| h[k] = k*k }   #=> {}
p = h.default_proc                 #=> #<Proc:0x401b3d08@-:1>
a = []                             #=> []
p.call(a, 2)
a                                  #=> [nil, nil, 4]
default_proc = proc_obj или nil Показать исходный код
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;
}

Устанавливает процедуру по умолчанию, которая должна выполняться при каждом неудачном поиске ключа.

h.default_proc = proc do |hash, key|
  hash[key] = key + key
end
h[2]       #=> 4
h["cat"]   #=> "catcat"
delete(key) → value Показать исходный код
delete(key) {| key | block } → value
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 (val != Qundef) {
        return val;
    }
    else {
        if (rb_block_given_p()) {
            return rb_yield(key);
        }
        else {
            return Qnil;
        }
    }
}

Удаляет пару «ключ-значение» и возвращает значение из hsh, ключ которого равен key. Если ключ не найден, возвращает nil. Если задан необязательный блок кода и ключ не найден, передайте ключ и верните результат block.

h = { "a" => 100, "b" => 200 }
h.delete("a")                              #=> 100
h.delete("z")                              #=> nil
h.delete("z") { |el| "#{el} not found" }   #=> "z not found"
delete_if {| key, value | block } → hsh Показать исходный код
delete_if → перечисление
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);
    }
    return hash;
}

Удаляет каждую пару «ключ-значение» из hsh, для которой block возвращает true.

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

h = { "a" => 100, "b" => 200, "c" => 300 }
h.delete_if {|key, value| key >= "b" }   #=> {"a"=>100}
dig(key, ...) → объект Показать исходный код
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, вызывая dig на каждом шаге, возвращая nil , если любой промежуточный шаг является nil .

h = { foo: {bar: {baz: 1}}}

h.dig(:foo, :bar, :baz)     #=> 1
h.dig(:foo, :zot, :xyz)     #=> nil

g = { foo: [10, 11, 12] }
g.dig(:foo, 1)              #=> 11
g.dig(:foo, 1, 0)           #=> TypeError: Integer does not have #dig method
g.dig(:foo, :bar)           #=> TypeError: no implicit conversion of Symbol into Integer
each {| ключ, значение | блок } → хш Показать исходный код
each_pair {| ключ, значение | блок } → хш
each → перечислитель
each_pair → перечислитель
static VALUE
rb_hash_each_pair(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    if (rb_block_arity() > 1)
        rb_hash_foreach(hash, each_pair_i_fast, 0);
    else
        rb_hash_foreach(hash, each_pair_i, 0);
    return hash;
}

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

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

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

результат:

a is 100
b is 200
each_key {| ключ | блок } → хш Показать исходный код
each_key → перечислитель
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;
}

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

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

h = { "a" => 100, "b" => 200 }
h.each_key {|key| puts key }

результат:

a
b
each_pair {| ключ, значение | блок } → хш Показать исходный код
each_pair → перечислитель
static VALUE
rb_hash_each_pair(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    if (rb_block_arity() > 1)
        rb_hash_foreach(hash, each_pair_i_fast, 0);
    else
        rb_hash_foreach(hash, each_pair_i, 0);
    return hash;
}

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

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

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

результат:

a is 100
b is 200
each_value {| значение | блок } → хш Показать исходный код
each_value → перечислитель
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;
}

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

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

h = { "a" => 100, "b" => 200 }
h.each_value {|value| puts value }

результат:

100
200
empty? → true или false Показать исходный код
static VALUE
rb_hash_empty_p(VALUE hash)
{
    return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
}

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

{}.empty?   #=> true
eql?(other) → true или false Показать исходный код
static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}

Возвращает true , если хэш и other — оба хэша с одинаковым содержанием. Порядок элементов хэшей не сравнивается.

END_OF_DOCUMENT_MARKER
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;
}

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

h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert   #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}

Если ключа с тем же значением нет, Hash#invert является инволютивным.

h = { a: 1, b: 3, c: 4 }
h.invert.invert == h #=> true

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

# no key with the same value
h = { a: 1, b: 3, c: 4 }
h.size == h.invert.size #=> true

# two (or more) keys has the same value
h = { a: 1, b: 3, c: 1 }
h.size == h.invert.size #=> false
keep_if {| key, value | block } → hsh Показать исходный код
keep_if → an_enumerator
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;
}

Удаляет каждую пару ключ-значение из hsh, для которой block возвращает false.

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

См. также Hash#select!.

key(value) → key Показать исходный код
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];
}

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

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
h.key(200)   #=> "b"
h.key(300)   #=> "c"
h.key(999)   #=> nil
key?(key) → true or false Показать исходный код
MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (hash_stlike_lookup(hash, key, NULL)) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}

Возвращает true, если заданный ключ присутствует в hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

Обратите внимание, что include? и member? не проверяют равенство членов, используя == так же, как и другие перечислители.

См. также Enumerable#include?

keys → array Показать исходный код
MJIT_FUNC_EXPORTED 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_TRANSIENT(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;
}

Возвращает новый массив, заполненный ключами из этого хэша. См. также Hash#values.

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
h.keys   #=> ["a", "b", "c", "d"]
length → integer Показать исходный код
VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}

Возвращает количество пар ключ-значение в хэше.

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.size          #=> 4
h.delete("a")   #=> 200
h.size          #=> 3
h.length        #=> 3

Hash#length является псевдонимом для Hash#size.

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

Возвращает true если заданный ключ присутствует в hsh.

h = { "a" => 100, "b" => 200 }
h.has_key?("a")   #=> true
h.has_key?("z")   #=> false

Обратите внимание, что include? и member? не проверяют равенство членов, используя == так же, как и другие перечислители.

См. также Enumerable#include?

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

Возвращает количество пар ключ-значение в хэше.

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
h.size          #=> 4
h.delete("a")   #=> 200
h.size          #=> 3
h.length        #=> 3

Hash#length является псевдонимом для Hash#size.

slice(*keys) → a_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 rb_hash_new();
    }
    result = rb_hash_new_with_size(argc);

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

    return result;
}

Возвращает хэш, содержащий только указанные ключи и их значения.

h = { a: 100, b: 200, c: 300 }
h.slice(:a)           #=> {:a=>100}
h.slice(:b, :c, :d)   #=> {:b=>200, :c=>300}
store(key, value) → value Показать исходный код
VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    int iter_lev = RHASH_ITER_LEV(hash);

    rb_hash_modify(hash);

    if (RHASH_TABLE_NULL_P(hash)) {
        if (iter_lev > 0) no_new_key();
        ar_alloc_table(hash);
    }

    if (RHASH_TYPE(hash) == &identhash || rb_obj_class(key) != rb_cString) {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
    }
    else {
        RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
    }
    return val;
}

Присвоение элемента

Связывает значение, заданное value, с ключом, заданным key.

h = { "a" => 100, "b" => 200 }
h["a"] = 9
h["c"] = 4
h   #=> {"a"=>9, "b"=>200, "c"=>4}
h.store("d", 42) #=> 42
h   #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}

Значение key не должно изменяться во время использования в качестве ключа (ключ, представляющий unfrozen String, будет дублирован и заморожен).

a = "a"
b = "b".freeze
h = { a => 100, b => 200 }
h.key(100).equal? a #=> false
h.key(200).equal? b #=> true
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;
}

Преобразует hsh в вложенный массив [ массивов ключ, значение ].

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
h.to_a   #=> [["c", 300], ["a", 100], ["d", 400]]
to_h → hsh или new_hash Показать исходный код
to_h {|ключ, значение| блок } → 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;
}

Возвращает self. Если вызов осуществляется для подкласса Hash, преобразует получатель в объект Hash.

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

to_hash → hsh Показать исходный код
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_proc_new(hash_proc_call, hash);
}

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

h = {a:1, b:2}
hp = h.to_proc
hp.call(:a)          #=> 1
hp.call(:b)          #=> 2
hp.call(:c)          #=> nil
[:a, :b, :c].map(&h) #=> [1, 2, nil]
to_s()
Псевдоним для: inspect
transform_keys {|ключ| блок } → new_hash Показать исходный код
transform_keys → перечислитель
static VALUE
rb_hash_transform_keys(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = rb_hash_new();
    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_foreach(hash, transform_keys_i, result);
    }

    return result;
}

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

h = { a: 1, b: 2, c: 3 }
h.transform_keys {|k| k.to_s }  #=> { "a" => 1, "b" => 2, "c" => 3 }
h.transform_keys(&:to_s)        #=> { "a" => 1, "b" => 2, "c" => 3 }
h.transform_keys.with_index {|k, i| "#{k}.#{i}" }
                                #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }

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

transform_keys! {|ключ| блок } → hsh Показать исходный код
transform_keys! → перечислитель
static VALUE
rb_hash_transform_keys_bang(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        long i;
        VALUE pairs = rb_hash_flatten(0, NULL, hash);
        rb_hash_clear(hash);
        for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
            VALUE key = RARRAY_AREF(pairs, i), new_key = rb_yield(key),
                  val = RARRAY_AREF(pairs, i+1);
            rb_hash_aset(hash, new_key, val);
        }
    }
    return hash;
}

Вызывает заданный блок один раз для каждого ключа в hsh, заменяя его новым ключом, возвращенным блоком, и затем возвращает hsh. Этот метод не изменяет значения.

h = { a: 1, b: 2, c: 3 }
h.transform_keys! {|k| k.to_s }  #=> { "a" => 1, "b" => 2, "c" => 3 }
h.transform_keys!(&:to_sym)      #=> { a: 1, b: 2, c: 3 }
h.transform_keys!.with_index {|k, i| "#{k}.#{i}" }
                                 #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }

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

transform_values {|значение| блок } → new_hash Показать исходный код
transform_values → перечислитель
static VALUE
rb_hash_transform_values(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = hash_copy(hash_alloc(rb_cHash), 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);
    }

    return result;
}

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

h = { a: 1, b: 2, c: 3 }
h.transform_values {|v| v * v + 1 }  #=> { a: 2, b: 5, c: 10 }
h.transform_values(&:to_s)           #=> { a: "1", b: "2", c: "3" }
h.transform_values.with_index {|v, i| "#{v}.#{i}" }
                                     #=> { a: "1.0", b: "2.1", c: "3.2" }

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

transform_values! {|значение| блок } → hsh Показать исходный код
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;
}

Вызывает заданный блок один раз для каждого значения в hsh, заменяя его новым значением, возвращенным блоком, и затем возвращает hsh. Этот метод не изменяет ключи.

h = { a: 1, b: 2, c: 3 }
h.transform_values! {|v| v * v + 1 }  #=> { a: 2, b: 5, c: 10 }
h.transform_values!(&:to_s)           #=> { a: "2", b: "5", c: "10" }
h.transform_values!.with_index {|v, i| "#{v}.#{i}" }
                                      #=> { a: "2.0", b: "5.1", c: "10.2" }

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

update(other_hash1, other_hash2, ...) → hsh Показать исходный код
update(other_hash1, other_hash2, ...) {|ключ, oldval, newval| блок}
static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
    int i;
    bool block_given = rb_block_given_p();

    rb_hash_modify(self);
    for (i = 0; i < argc; i++){
       VALUE hash = to_hash(argv[i]);
       if (block_given) {
           rb_hash_foreach(hash, rb_hash_update_block_i, self);
       }
       else {
           rb_hash_foreach(hash, rb_hash_update_i, self);
       }
    }
    return self;
}

Добавляет содержимое заданных хэшей к получателю.

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

h1 = { "a" => 100, "b" => 200 }
h1.merge!          #=> {"a"=>100, "b"=>200}
h1                 #=> {"a"=>100, "b"=>200}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 246, "c" => 300 }
h1.merge!(h2)      #=> {"a"=>100, "b"=>246, "c"=>300}
h1                 #=> {"a"=>100, "b"=>246, "c"=>300}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 246, "c" => 300 }
h3 = { "b" => 357, "d" => 400 }
h1.merge!(h2, h3)
                   #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
h1                 #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 246, "c" => 300 }
h3 = { "b" => 357, "d" => 400 }
h1.merge!(h2, h3) {|key, v1, v2| v1 }
                   #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
h1                 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}

Hash#update является псевдонимом для Hash#merge!.

value?(значение) → true или 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];
}

Возвращает true если заданное значение присутствует для некоторого ключа в hsh.

h = { "a" => 100, "b" => 200 }
h.value?(100)   #=> true
h.value?(999)   #=> false
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_TRANSIENT(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_TRANSIENT(values, ptr, {
                size = st_values(table, ptr, size);
            });
        }
        rb_ary_set_len(values, size);
    }
    else {
        rb_hash_foreach(hash, values_i, values);
    }

    return values;
}

Возвращает новый массив, заполненный значениями из hsh. См. также Hash#keys.

h = { "a" => 100, "b" => 200, "c" => 300 }
h.values   #=> [100, 200, 300]
values_at(ключ, ...) → массив Показать исходный код
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;
}

Возвращает массив, содержащий значения, связанные с заданными ключами. См. также Hash.select.

h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
h.values_at("cow", "cat")  #=> ["bovine", "feline"]

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

Spec-Zone.ru

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