class Hash

A Hash object maps each of its unique keys to a specific value.

A hash has certain similarities to an Array, but:

Hash Data Syntax

The original syntax for a hash entry uses the “hash rocket,” =>:

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

Alternatively, but only for a key that’s a symbol, you can use a newer JSON-style syntax, where each bareword becomes a symbol:

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

You can also use a string in place of a bareword:

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

And you can mix the styles:

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

But it’s an error to try the JSON-style syntax for a key that’s not a bareword or a string:

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

The value can be omitted, meaning that value will be fetched from the context by the name of the key:

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

Common Uses

You can use a hash to give names to objects:

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

You can use a hash to give names to method arguments:

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

Note: when the last argument in a method call is a hash, the curly braces may be omitted:

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

You can use a hash to initialize an object:

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

Creating a Hash

You can create a Hash object explicitly with:

You can convert certain objects to hashes with:

You can create a hash by calling method Hash.new:

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

You can create a hash by calling method Hash.[]:

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

You can create a hash by using its literal form (curly braces):

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

Hash Value Basics

The simplest way to retrieve a hash value (instance method []):

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

The simplest way to create or update a hash value (instance method []=):

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}

The simplest way to delete a hash entry (instance method delete):

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

Entry Order

A Hash object presents its entries in the order of their creation. This is seen in:

A new hash has its initial ordering per the given entries:

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

New entries are added at the end:

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

Updating a value does not affect the order:

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

But re-creating a deleted entry can affect the order:

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

Hash Keys

Hash Key Equivalence

Two objects are treated as the same hash key when their hash value is identical and the two objects are eql? to each other.

Modifying an Active Hash Key

Modifying a Hash key while it is in use damages the hash’s index.

This Hash has keys that are Arrays:

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

Modifying array element a0[0] changes its hash value:

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

And damages the Hash index:

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

You can repair the hash index using method rehash:

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

A String key is always safe. That’s because an unfrozen String passed as a key will be replaced by a duplicated and frozen String:

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

User-Defined Hash Keys

To be usable as a Hash key, objects must implement the methods hash and eql?. Note: this requirement does not apply if the Hash uses compare_by_identity since comparison will then rely on the keys’ object id instead of hash and eql?.

Object defines basic implementation for hash and eq? that makes each object a distinct key. Typically, user-defined classes will want to override these methods to provide meaningful behavior, or for example inherit Struct that has useful definitions for these.

A typical implementation of hash is based on the object’s data while eql? is usually aliased to the overridden == method:

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

Key Not Found?

When a method tries to retrieve and return the value for a key and that key is found, the returned value is the value associated with the key.

But what if the key is not found? In that case, certain methods will return a default value while other will raise a KeyError.

Nil Return Value

If you want nil returned for a not-found key, you can call:

You can override these behaviors for [], dig, and values_at (but not assoc); see Hash Default.

KeyError

If you want KeyError raised for a not-found key, you can call:

Hash Default

For certain methods ([], dig, and values_at), the return value for a not-found key is determined by two hash properties:

In the simple case, both values are nil, and the methods return nil for a not-found key; see Nil Return Value above.

Note that this entire section (“Hash Default”):

Any-Key Default

You can define an any-key default for a hash; that is, a value that will be returned for any not-found key:

You can set the default value when the hash is created with Hash.new and option default_value, or later with method default=.

Note: although the value of default may be any object, it may not be a good idea to use a mutable object.

Per-Key Defaults

You can define a per-key default for a hash; that is, a Proc that will return a value based on the key itself.

You can set the default proc when the hash is created with Hash.new and a block, or later with method default_proc=.

Note that the proc can modify self, but modifying self in this way is not thread-safe; multiple threads can concurrently call into the default proc for the same key.

Method Default

For two methods, you can specify a default value for a not-found key that has effect only for a single method call (and not for any subsequent calls):

What’s Here

First, what’s elsewhere. Class Hash:

Here, class Hash provides methods that are useful for:

Class Hash also includes methods from module Enumerable.

Methods for Creating a Hash

Methods for Setting Hash State

Methods for Querying

Methods for Comparing

Methods for Fetching

Methods for Assigning

Methods for Deleting

These methods remove entries from self:

These methods return a copy of self with some entries removed:

Methods for Iterating

Methods for Converting

Methods for Transforming Keys and Values

Public Class Methods

Hash[] → new_empty_hash click to toggle source
Hash[other_hash] → new_hash
Hash[ [*2_element_arrays] ] → new_hash
Hash[*objects] → new_hash

Returns a new Hash object populated with the given objects, if any. See Hash::new.

With no argument given, returns a new empty hash.

With a single argument other_hash given that is a hash, returns a new hash initialized with the entries from that hash (but not with its default or default_proc):

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

With a single argument 2_element_arrays given that is an array of 2-element arrays, returns a new hash wherein each given 2-element array forms a key-value entry:

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

With an even number of arguments objects given, returns a new hash wherein each successive pair of arguments is a key-value entry:

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

Raises ArgumentError if the argument list does not conform to any of the above.

See also Methods for Creating a 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;
}
new(default_value = nil, capacity: 0) → new_hash click to toggle source
new(capacity: 0) {|self, key| ... } → new_hash

Returns a new empty Hash object.

Initializes the values of Hash#default and Hash#default_proc, which determine the behavior when a given key is not found; see Key Not Found?.

By default, a hash has nil values for both default and default_proc:

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

With argument default_value given, sets the default value for the hash:

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

With a block given, sets the default_proc value:

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

Raises ArgumentError if both default_value and a block are given.

If optional keyword argument capacity is given with a positive integer value n, initializes the hash with enough capacity to accommodate n entries without resizing.

See also Methods for Creating a 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
ruby2_keywords_hash(hash) → hash click to toggle source

Duplicates a given hash and adds a ruby2_keywords flag. This method is not for casual use; debugging, researching, and some truly necessary cases like deserialization of arguments.

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
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_hash?(hash) → true or false click to toggle source

Checks if a given hash is flagged by Module#ruby2_keywords (or Proc#ruby2_keywords). This method is not for casual use; debugging, researching, and some truly necessary cases like serialization of arguments.

ruby2_keywords def foo(*args)
  Hash.ruby2_keywords_hash?(args.last)
end
foo(k: 1)   #=> true
foo({k: 1}) #=> 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);
}
try_convert(object) → object, new_hash, or nil click to toggle source

If object is a hash, returns object.

Otherwise if object responds to :to_hash, calls object.to_hash; returns the result if it is a hash, or raises TypeError if not.

Otherwise if object does not respond to :to_hash, returns nil.

static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
    return rb_check_hash_type(hash);
}

Public Instance Methods

self < other → true or false click to toggle source

Returns whether the entries of self are a proper subset of the entries of other:

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

See Hash Inclusion.

Raises TypeError if other_hash is not a hash and cannot be converted to a hash.

Related: see Methods for Comparing.

static VALUE
rb_hash_lt(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) >= RHASH_SIZE(other)) return Qfalse;
    return hash_le(hash, other);
}
self <= other → true or false click to toggle source

Returns whether the entries of self are a subset of the entries of other:

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

See Hash Inclusion.

Raises TypeError if other_hash is not a hash and cannot be converted to a hash.

Related: see Methods for Comparing.

static VALUE
rb_hash_le(VALUE hash, VALUE other)
{
    other = to_hash(other);
    if (RHASH_SIZE(hash) > RHASH_SIZE(other)) return Qfalse;
    return hash_le(hash, other);
}
self == other → true or false click to toggle source

Returns whether all of the following are true:

  • other is a Hash object (or can be converted to one).

  • self and other have the same keys (regardless of order).

  • For each key key, self[key] == other[key].

Examples:

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

Related: see Methods for Comparing.

static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}
self > other → true or false click to toggle source

Returns whether the entries of self are a proper superset of the entries of other:

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

See Hash Inclusion.

Raises TypeError if other_hash is not a hash and cannot be converted to a hash.

Related: see Methods for Comparing.

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);
}
self >= other → true or false click to toggle source

Returns whether the entries of self are a superset of the entries of other:

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

See Hash Inclusion.

Raises TypeError if other_hash is not a hash and cannot be converted to a hash.

Related: see Methods for Comparing.

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);
}
self[key] → object click to toggle source

Searches for a hash key equivalent to the given key; see Hash Key Equivalence.

If the key is found, returns its value:

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

Otherwise, returns a default value (see Hash Default).

Related: []=; see also Methods for Fetching.

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);
    }
}
self[key] = object → object click to toggle source

Associates the given object with the given key; returns object.

Searches for a hash key equivalent to the given key; see Hash Key Equivalence.

If the key is found, replaces its value with the given object; the ordering is not affected (see Entry Order):

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

If key is not found, creates a new entry for the given key and object; the new entry is last in the order (see Entry Order):

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

Related: []; see also Methods for Assigning.

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;
}
Also aliased as: store
any? → true or false click to toggle source
any?(entry) → true or false
any? {|key, value| ... } → true or false

Returns true if any element satisfies a given criterion; false otherwise.

If self has no element, returns false and argument or block are not used; otherwise behaves as below.

With no argument and no block, returns true if self is non-empty, false otherwise.

With argument entry and no block, returns true if for any key key self.assoc(key) == entry, false otherwise:

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

With no argument and a block given, calls the block with each key-value pair; returns true if the block returns a truthy value, false otherwise:

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

With both argument entry and a block given, issues a warning and ignores the block.

Related: Enumerable#any? (which this method overrides); see also Methods for Fetching.

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];
}
assoc(key) → entry or nil click to toggle source

If the given key is found, returns its entry as a 2-element array containing that key and its value:

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

Returns nil if the key is not found.

Related: see Methods for Fetching.

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];
}
clear → self click to toggle source

Removes all entries from self; returns emptied self.

Related: see Methods for Deleting.

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;
}
compact → new_hash click to toggle source

Returns a copy of self with all nil-valued entries removed:

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

Related: see Methods for Deleting.

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;
}
compact! → self or nil click to toggle source

If self contains any nil-valued entries, returns self with all nil-valued entries removed; returns nil otherwise:

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

Related: see Methods for Deleting.

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;
}
compare_by_identity → self click to toggle source

Sets self to compare keys using identity (rather than mere equality); returns self:

By default, two keys are considered to be the same key if and only if they are equal objects (per method eql?):

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

When this method has been called, two keys are considered to be the same key if and only if they are the same object:

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

Related: compare_by_identity?; see also Methods for Comparing.

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

    rb_gc_register_pinning_obj(hash);

    return hash;
}
compare_by_identity? → true or false click to toggle source

Returns whether compare_by_identity has been called:

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

Related: compare_by_identity; see also Methods for Comparing.

VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    return RBOOL(RHASH_IDENTHASH_P(hash));
}
default → object click to toggle source
default(key) → object

Returns the default value for the given key. The returned value will be determined either by the default proc or by the default value. See Hash Default.

With no argument, returns the current default value:

h = {}
h.default # => nil

If key is given, returns the default value for key, regardless of whether that key exists:

h = Hash.new { |hash, key| hash[key] = "No key #{key}"}
h[:foo] = "Hello"
h.default(:foo) # => "No key foo"
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;
}
default = value → object click to toggle source

Sets the default value to value; returns value:

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

See Hash Default.

VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
    rb_hash_modify_check(hash);
    SET_DEFAULT(hash, ifnone);
    return ifnone;
}
default_proc → proc or nil click to toggle source

Returns the default proc for self (see Hash Default):

h = {}
h.default_proc # => nil
h.default_proc = proc {|hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
static VALUE
rb_hash_default_proc(VALUE hash)
{
    if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
        return RHASH_IFNONE(hash);
    }
    return Qnil;
}
default_proc = proc → proc click to toggle source

Sets the default proc for self to proc (see Hash Default):

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
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;
}
delete(key) → value or nil click to toggle source
delete(key) {|key| ... } → object

If an entry for the given key is found, deletes the entry and returns its associated value; otherwise returns nil or calls the given block.

With no block given and key found, deletes the entry and returns its value:

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

With no block given and key not found, returns nil.

With a block given and key found, ignores the block, deletes the entry, and returns its value:

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

With a block given and key not found, calls the block and returns the block’s return value:

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}

Related: see Methods for Deleting.

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;
        }
    }
}
delete_if {|key, value| ... } → self click to toggle source
delete_if → new_enumerator

With a block given, calls the block with each key-value pair, deletes each entry for which the block returns a truthy value, and returns self:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
dig(key, *identifiers) → object click to toggle source

Finds and returns an object found in nested objects, as specified by key and identifiers.

The nested objects may be instances of various classes. See Dig Methods.

Nested hashes:

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

Nested hashes and arrays:

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

If no such object is found, returns the hash default:

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

Related: Methods for Fetching.

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);
}
each()

With a block given, calls the block with each key-value pair; returns self:

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

Output:

foo: 0
bar: 1
baz: 2

With no block given, returns a new Enumerator.

Related: see Methods for Iterating.

Alias for: each_pair
each_key {|key| ... } → self click to toggle source
each_key → new_enumerator

With a block given, calls the block with each key; returns self:

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

Output:

foo
bar
baz

With no block given, returns a new Enumerator.

Related: see Methods for Iterating.

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;
}
each_pair {|key, value| ... } → self click to toggle source
each_pair → new_enumerator

With a block given, calls the block with each key-value pair; returns self:

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

Output:

foo: 0
bar: 1
baz: 2

With no block given, returns a new Enumerator.

Related: see Methods for Iterating.

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;
}
Also aliased as: each
each_value {|value| ... } → self click to toggle source
each_value → new_enumerator

With a block given, calls the block with each value; returns self:

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

Output:

0
1
2

With no block given, returns a new Enumerator.

Related: see Methods for Iterating.

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;
}
empty? → true or false click to toggle source

Returns true if there are no hash entries, false otherwise:

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

Related: see Methods for Querying.

VALUE
rb_hash_empty_p(VALUE hash)
{
    return RBOOL(RHASH_EMPTY_P(hash));
}
eql?(object) → true or false click to toggle source

Returns true if all of the following are true:

  • The given object is a Hash object.

  • self and object have the same keys (regardless of order).

  • For each key key, self[key].eql?(object[key]).

Otherwise, returns 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

Related: see Methods for Querying.

static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}
except(*keys) → new_hash click to toggle source

Returns a copy of self that excludes entries for the given keys; any keys that are not found are ignored:

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

Related: see Methods for Deleting.

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;
}
fetch(key) → object click to toggle source
fetch(key, default_value) → object
fetch(key) {|key| ... } → object

With no block given, returns the value for the given key, if found;

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

If the key is not found, returns default_value, if given, or raises KeyError otherwise:

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

With a block given, calls the block with key and returns the block’s return value:

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

Note that this method does not use the values of either default or default_proc.

Related: see Methods for Fetching.

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];
        }
    }
}
fetch_values(*keys) → new_array click to toggle source
fetch_values(*keys) {|key| ... } → new_array

When all given keys are found, returns a new array containing the values associated with the given keys:

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

When any given keys are not found and a block is given, calls the block with each unfound key and uses the block’s return value as the value for that key:

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

When any given keys are not found and no block is given, raises KeyError.

Related: see Methods for Fetching.

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;
}
filter()

With a block given, calls the block with each entry’s key and value; returns a new hash whose entries are those for which the block returns a truthy value:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

Alias for: select
filter!()

With a block given, calls the block with each entry’s key and value; removes from self each entry for which the block returns false or nil.

Returns self if any entries were removed, nil otherwise:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

Alias for: select!
flatten(depth = 1) → new_array click to toggle source

With positive integer depth, returns a new array that is a recursive flattening of self to the given depth.

At each level of recursion:

  • Each element whose value is an array is “flattened” (that is, replaced by its individual array elements); see Array#flatten.

  • Each element whose value is not an array is unchanged. even if the value is an object that has instance method flatten (such as a hash).

Examples; note that entry foo: {bar: 1, baz: 2} is never flattened.

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

With negative integer depth, flattens all levels:

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

With depth zero, returns the equivalent of to_a:

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

Related: see Methods for Converting.

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;
}
has_key?(p1)

Returns whether key is a key in self:

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

Related: Methods for Querying.

Alias for: include?
has_value?(value) -> true or false click to toggle source

Returns whether value is a value in self.

Related: Methods for Querying.

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];
}
Also aliased as: value?
hash → an_integer click to toggle source

Returns the integer hash-code for the hash.

Two hashes have the same hash-code if their content is the same (regardless of order):

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

Related: see Methods for Querying.

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);
}
include?(key) → true or false click to toggle source

Returns whether key is a key in self:

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

Related: Methods for Querying.

VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}
Also aliased as: member?, has_key?, key?
initialize_copy(other_hash) -> self click to toggle source

Replaces the entire contents of self with the contents of other_hash; returns self:

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

Also replaces the default value or proc of self with the default value or proc of other_hash.

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

Related: see Methods for Assigning.

static VALUE
rb_hash_replace(VALUE hash, VALUE hash2)
{
    rb_hash_modify_check(hash);
    if (hash == hash2) return hash;
    if (hash_iterating_p(hash)) {
        rb_raise(rb_eRuntimeError, "can't replace hash during iteration");
    }
    hash2 = to_hash(hash2);

    COPY_DEFAULT(hash, hash2);

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

    hash_copy(hash, hash2);

    return hash;
}
Also aliased as: replace
inspect → new_string click to toggle source

Returns a new string containing the hash entries:

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

Related: see Methods for Converting.

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);
}
Also aliased as: to_s
invert → new_hash click to toggle source

Returns a new hash with each key-value pair inverted:

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

Overwrites any repeated new keys (see Entry Order):

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

Related: see Methods for Transforming Keys and Values.

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;
}
keep_if {|key, value| ... } → self click to toggle source
keep_if → new_enumerator

With a block given, calls the block for each key-value pair; retains the entry if the block returns a truthy value; otherwise deletes the entry; returns self:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
key(value) → key or nil click to toggle source

Returns the key for the first-found entry with the given value (see Entry Order):

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

Returns nil if no such value is found.

Related: see Methods for Fetching.

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];
}
key?(p1)

Returns whether key is a key in self:

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

Related: Methods for Querying.

Alias for: include?
keys → new_array click to toggle source

Returns a new array containing all keys in self:

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

Related: see Methods for Fetching.

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;
}
length()

Returns the count of entries in self:

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

Related: see Methods for Querying.

Alias for: size
member?(p1)

Returns whether key is a key in self:

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

Related: Methods for Querying.

Alias for: include?
merge(*other_hashes) → new_hash click to toggle source
merge(*other_hashes) { |key, old_value, new_value| ... } → new_hash

Each argument other_hash in other_hashes must be a hash.

With arguments other_hashes given and no block, returns the new hash formed by merging each successive other_hash into a copy of self; returns that copy; for each successive entry in other_hash:

  • For a new key, the entry is added at the end of self.

  • For duplicate key, the entry overwrites the entry in self, whose position is unchanged.

Example:

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}

With arguments other_hashes and a block given, behaves as above except that for a duplicate key the overwriting entry takes it value not from the entry in other_hash, but instead from the block:

  • The block is called with the duplicate key and the values from both self and other_hash.

  • The block’s return value becomes the new value for the entry in self.

Example:

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

With no arguments, returns a copy of self; the block, if given, is ignored.

Related: see Methods for Assigning.

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));
}
merge!(*args)

Updates values and/or adds entries to self; returns self.

Each argument other_hash in other_hashes must be a hash.

With no block given, for each successive entry key/new_value in each successive other_hash:

  • If key is in self, sets self[key] = new_value, whose position is unchanged:

    h0 = {foo: 0, bar: 1, baz: 2}
    h1 = {bar: 3, foo: -1}
    h0.update(h1) # => {foo: -1, bar: 3, baz: 2}
    
  • If key is not in self, adds the entry at the end of self:

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

With a block given, for each successive entry key/new_value in each successive other_hash:

  • If key is in self, fetches old_value from self[key], calls the block with key, old_value, and new_value, and sets self[key] = new_value, whose position is unchanged :

    season = {AB: 75, H: 20, HR: 3, SO: 17, W: 11, HBP: 3}
    today = {AB: 3, H: 1, W: 1}
    yesterday = {AB: 4, H: 2, HR: 1}
    season.update(yesterday, today) {|key, old_value, new_value| old_value + new_value }
    # => {AB: 82, H: 23, HR: 4, SO: 17, W: 12, HBP: 3}
    
  • If key is not in self, adds the entry at the end of self:

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

Related: see Methods for Assigning.

Alias for: update
rassoc(value) → new_array or nil click to toggle source

Searches self for the first entry whose value is == to the given value; see Entry Order.

If the entry is found, returns its key and value as a 2-element array; returns nil if not found:

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

Related: see Methods for Fetching.

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];
}
rehash → self click to toggle source

Rebuilds the hash table for self by recomputing the hash index for each key; returns self. Calling this method ensures that the hash table is valid.

The hash table becomes invalid if the hash value of a key has changed after the entry was created. See Modifying an Active Hash Key.

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;
}
reject {|key, value| ... } → new_hash click to toggle source
reject → new_enumerator

With a block given, returns a copy of self with zero or more entries removed; calls the block with each key-value pair; excludes the entry in the copy if the block returns a truthy value, includes it otherwise:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
reject! {|key, value| ... } → self or nil click to toggle source
reject! → new_enumerator

With a block given, calls the block with each entry’s key and value; removes the entry from self if the block returns a truthy value.

Return self if any entries were removed, nil otherwise:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
replace(other_hash) → self

Replaces the entire contents of self with the contents of other_hash; returns self:

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

Also replaces the default value or proc of self with the default value or proc of other_hash.

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

Related: see Methods for Assigning.

Alias for: initialize_copy
select {|key, value| ... } → new_hash click to toggle source
select → new_enumerator

With a block given, calls the block with each entry’s key and value; returns a new hash whose entries are those for which the block returns a truthy value:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
Also aliased as: filter
select! {|key, value| ... } → self or nil click to toggle source
select! → new_enumerator

With a block given, calls the block with each entry’s key and value; removes from self each entry for which the block returns false or nil.

Returns self if any entries were removed, nil otherwise:

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

With no block given, returns a new Enumerator.

Related: see Methods for Deleting.

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;
}
Also aliased as: filter!
shift → [key, value] or nil click to toggle source

Removes and returns the first entry of self as a 2-element array; see Entry Order:

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

Returns nil if self is empty.

Related: see Methods for Deleting.

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;
}
size → integer click to toggle source

Returns the count of entries in self:

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

Related: see Methods for Querying.

VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}
Also aliased as: length
slice(*keys) → new_hash click to toggle source

Returns a new hash containing the entries from self for the given keys; ignores any keys that are not found:

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

Related: see Methods for Deleting.

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;
}
store(p1, p2)

Associates the given object with the given key; returns object.

Searches for a hash key equivalent to the given key; see Hash Key Equivalence.

If the key is found, replaces its value with the given object; the ordering is not affected (see Entry Order):

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

If key is not found, creates a new entry for the given key and object; the new entry is last in the order (see Entry Order):

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

Related: []; see also Methods for Assigning.

Alias for: []=
to_a → new_array click to toggle source

Returns all elements of self as an array of 2-element arrays; each nested array contains a key-value pair from self:

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

Related: see Methods for Converting.

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;
}
to_h {|key, value| ... } → new_hash click to toggle source
to_h → self or new_hash

With a block given, returns a new hash whose content is based on the block; the block is called with each entry’s key and value; the block should return a 2-element array containing the key and value to be included in the returned array:

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

With no block given, returns self if self is an instance of Hash; if self is a subclass of Hash, returns a new hash containing the content of self.

Related: see Methods for Converting.

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;
}
to_hash → self click to toggle source

Returns self.

Related: see Methods for Converting.

static VALUE
rb_hash_to_hash(VALUE hash)
{
    return hash;
}
to_proc → proc click to toggle source

Returns a Proc object that maps a key to its value:

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
h.default_proc = proc { |hash, key| "Missing key: #{key}" } # This affect the existing proc object
proc.call(:nosuch) # => "Missing key: #{nosuch}"

Related: see Methods for Converting.

static VALUE
rb_hash_to_proc(VALUE hash)
{
    return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
}
to_s()

Returns a new string containing the hash entries:

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

Related: see Methods for Converting.

Alias for: inspect
transform_keys {|old_key| ... } → new_hash click to toggle source
transform_keys(other_hash) → new_hash
transform_keys(other_hash) {|old_key| ...} → new_hash
transform_keys → new_enumerator

With an argument, a block, or both given, derives a new hash new_hash from self, the argument, and/or the block; all, some, or none of its keys may be different from those in self.

With a block given and no argument, new_hash has keys determined only by the block.

For each key/value pair old_key/value in self, calls the block with old_key; the block’s return value becomes new_key; sets new_hash[new_key] = value; a duplicate key overwrites:

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

With argument other_hash given and no block, new_hash may have new keys provided by other_hash and unchanged keys provided by self.

For each key/value pair old_key/old_value in self, looks for key old_key in other_hash:

  • If old_key is found, its value other_hash[old_key] is taken as new_key; sets new_hash[new_key] = value; a duplicate key overwrites:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO)
    # => {FOO: 0, BAR: 1, BAZ: 2}
    h.transform_keys(baz: :FOO, bar: :FOO, foo: :FOO)
    # => {FOO: 2}
    
  • If old_key is not found, sets new_hash[old_key] = value; a duplicate key overwrites:

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

Unused keys in other_hash are ignored:

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

With both argument other_hash and a block given, new_hash has new keys specified by other_hash or by the block, and unchanged keys provided by self.

For each pair old_key and value in self:

  • If other_hash has key old_key (with value new_key), does not call the block for that key; sets new_hash[new_key] = value; a duplicate key overwrites:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
    # => {FOO: 0, BAR: 1, BAZ: 2}
    
  • If other_hash does not have key old_key, calls the block with old_key and takes its return value as new_key; sets new_hash[new_key] = value; a duplicate key overwrites:

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

With no argument and no block given, returns a new Enumerator.

Related: see Methods for Transforming Keys and Values.

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;
}
transform_keys! {|old_key| ... } → self click to toggle source
transform_keys!(other_hash) → self
transform_keys!(other_hash) {|old_key| ...} → self
transform_keys! → new_enumerator

With an argument, a block, or both given, derives keys from the argument, the block, and self; all, some, or none of the keys in self may be changed.

With a block given and no argument, derives keys only from the block; all, some, or none of the keys in self may be changed.

For each key/value pair old_key/value in self, calls the block with old_key; the block’s return value becomes new_key; removes the entry for old_key: self.delete(old_key); sets self[new_key] = value; a duplicate key overwrites:

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

With argument other_hash given and no block, derives keys for self from other_hash and self; all, some, or none of the keys in self may be changed.

For each key/value pair old_key/old_value in self, looks for key old_key in other_hash:

  • If old_key is found, takes value other_hash[old_key] as new_key; removes the entry for old_key: self.delete(old_key); sets self[new_key] = value; a duplicate key overwrites:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO)
    # => {FOO: 0, BAR: 1, BAZ: 2}
    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :FOO, bar: :FOO, foo: :FOO)
    # => {FOO: 2}
    
  • If old_key is not found, does nothing:

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

Unused keys in other_hash are ignored:

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

With both argument other_hash and a block given, derives keys from other_hash, the block, and self; all, some, or none of the keys in self may be changed.

For each pair old_key and value in self:

  • If other_hash has key old_key (with value new_key), does not call the block for that key; removes the entry for old_key: self.delete(old_key); sets self[new_key] = value; a duplicate key overwrites:

    h = {foo: 0, bar: 1, baz: 2}
    h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
    # => {FOO: 0, BAR: 1, BAZ: 2}
    
  • If other_hash does not have key old_key, calls the block with old_key and takes its return value as new_key; removes the entry for old_key: self.delete(old_key); sets self[new_key] = value; a duplicate key overwrites:

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

With no argument and no block given, returns a new Enumerator.

Related: see Methods for Transforming Keys and Values.

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;
}
transform_values {|value| ... } → new_hash click to toggle source
transform_values → new_enumerator

With a block given, returns a new hash new_hash; for each pair key/value in self, calls the block with value and captures its return as new_value; adds to new_hash the entry key/new_value:

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

With no block given, returns a new Enumerator.

Related: see Methods for Transforming Keys and 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)) {
        transform_values(result);
        compact_after_delete(result);
    }

    return result;
}
transform_values! {|old_value| ... } → self click to toggle source
transform_values! → new_enumerator

With a block given, changes the values of self as determined by the block; returns self.

For each entry key/old_value in self, calls the block with old_value, captures its return value as new_value, and sets self[key] = new_value:

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

With no block given, returns a new Enumerator.

Related: see Methods for Transforming Keys and 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)) {
        transform_values(hash);
    }

    return hash;
}
update(*other_hashes) → self click to toggle source
update(*other_hashes) { |key, old_value, new_value| ... } → self

Updates values and/or adds entries to self; returns self.

Each argument other_hash in other_hashes must be a hash.

With no block given, for each successive entry key/new_value in each successive other_hash:

  • If key is in self, sets self[key] = new_value, whose position is unchanged:

    h0 = {foo: 0, bar: 1, baz: 2}
    h1 = {bar: 3, foo: -1}
    h0.update(h1) # => {foo: -1, bar: 3, baz: 2}
    
  • If key is not in self, adds the entry at the end of self:

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

With a block given, for each successive entry key/new_value in each successive other_hash:

  • If key is in self, fetches old_value from self[key], calls the block with key, old_value, and new_value, and sets self[key] = new_value, whose position is unchanged :

    season = {AB: 75, H: 20, HR: 3, SO: 17, W: 11, HBP: 3}
    today = {AB: 3, H: 1, W: 1}
    yesterday = {AB: 4, H: 2, HR: 1}
    season.update(yesterday, today) {|key, old_value, new_value| old_value + new_value }
    # => {AB: 82, H: 23, HR: 4, SO: 17, W: 12, HBP: 3}
    
  • If key is not in self, adds the entry at the end of self:

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

Related: see Methods for Assigning.

static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
    struct update_call_args args = {
        .hash = self,
        .argv = argv,
        .argc = argc,
        .block_given = rb_block_given_p(),
        .iterating = false,
    };
    VALUE arg = (VALUE)&args;

    rb_hash_modify(self);
    return rb_ensure(rb_hash_update_call, arg, rb_hash_update_ensure, arg);
}
Also aliased as: merge!
value?(p1)

Returns whether value is a value in self.

Related: Methods for Querying.

Alias for: has_value?
values → new_array click to toggle source

Returns a new array containing all values in self:

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

Related: see Methods for Fetching.

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;
}
values_at(*keys) → new_array click to toggle source

Returns a new array containing values for the given keys:

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

The hash default is returned for each key that is not found:

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

Related: see Methods for Fetching.

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