Class: Hash

Inherits:
Object show all
Includes:
Enumerable
Defined in:
hash.c

Overview

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

A Hash has certain similarities to an Array, but:

  • An Array index is always an Integer.

  • A Hash key can be (almost) any object.

Hash Data Syntax

The older syntax for Hash data uses the “hash rocket,” =>:

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

Alternatively, but only for a Hash 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'}

Hash 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:

  • Method #Hash.

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:

  • Iterative methods such as each, each_key, each_pair, each_value.

  • Other order-sensitive methods such as shift, keys, values.

  • The String returned by method inspect.

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

Default Values

The methods #[], #values_at and #dig need to return the value associated to a certain key. When that key is not found, that value will be determined by its default proc (if any) or else its default (initially ‘nil`).

You can retrieve the default value with method #default:

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

You can set the default value by passing an argument to method Hash.new or with method #default=

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

This default value is returned for #[], #values_at and #dig when a key is not found:

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

Note that the default value is used without being duplicated. It is not advised to set the default value to a mutable object:

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

To use a mutable object as default, it is recommended to use a default proc

Default Proc

When the default proc for a Hash is set (i.e., not nil), the default value returned by method #[] is determined by the default proc alone.

You can retrieve the default proc with method #default_proc:

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

You can set the default proc by calling Hash.new with a block or calling the method #default_proc=

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

When the default proc is set (i.e., not nil) and method #[] is called with with a non-existent key, #[] calls the default proc with both the Hash object itself and the missing key, then returns the proc’s return value:

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

Note that in the example above no entry for key :nosuch is created:

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

However, the proc itself can add a new entry:

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

Note that setting the default proc will clear the default value and vice versa.

Be aware that a default proc that modifies the hash is not thread-safe in the sense that multiple threads can call into the default proc concurrently for the same key.

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

  • ::[]: Returns a new hash populated with given objects.

  • ::new: Returns a new empty hash.

  • ::try_convert: Returns a new hash created from a given object.

Methods for Setting Hash State

  • #compare_by_identity: Sets self to consider only identity in comparing keys.

  • #default=: Sets the default to a given value.

  • #default_proc=: Sets the default proc to a given proc.

  • #rehash: Rebuilds the hash table by recomputing the hash index for each key.

Methods for Querying

  • #any?: Returns whether any element satisfies a given criterion.

  • #compare_by_identity?: Returns whether the hash considers only identity when comparing keys.

  • #default: Returns the default value, or the default value for a given key.

  • #default_proc: Returns the default proc.

  • #empty?: Returns whether there are no entries.

  • #eql?: Returns whether a given object is equal to self.

  • #hash: Returns the integer hash code.

  • #has_value? (aliased as #value?): Returns whether a given object is a value in self.

  • #include? (aliased as #has_key?, #member?, #key?): Returns whether a given object is a key in self.

  • #size (aliased as #length): Returns the count of entries.

Methods for Comparing

  • #<: Returns whether self is a proper subset of a given object.

  • #<=: Returns whether self is a subset of a given object.

  • #==: Returns whether a given object is equal to self.

  • #>: Returns whether self is a proper superset of a given object

  • #>=: Returns whether self is a superset of a given object.

Methods for Fetching

  • #[]: Returns the value associated with a given key.

  • #assoc: Returns a 2-element array containing a given key and its value.

  • #dig: Returns the object in nested objects that is specified by a given key and additional arguments.

  • #fetch: Returns the value for a given key.

  • #fetch_values: Returns array containing the values associated with given keys.

  • #key: Returns the key for the first-found entry with a given value.

  • #keys: Returns an array containing all keys in self.

  • #rassoc: Returns a 2-element array consisting of the key and value of the first-found entry having a given value.

  • #values: Returns an array containing all values in self/

  • #values_at: Returns an array containing values for given keys.

Methods for Assigning

  • #[]= (aliased as #store): Associates a given key with a given value.

  • #merge: Returns the hash formed by merging each given hash into a copy of self.

  • #update (aliased as #merge!): Merges each given hash into self.

  • #replace (aliased as #initialize_copy): Replaces the entire contents of self with the contents of a given hash.

Methods for Deleting

These methods remove entries from self:

  • #clear: Removes all entries from self.

  • #compact!: Removes all nil-valued entries from self.

  • #delete: Removes the entry for a given key.

  • #delete_if: Removes entries selected by a given block.

  • #select! (aliased as #filter!): Keep only those entries selected by a given block.

  • #keep_if: Keep only those entries selected by a given block.

  • #reject!: Removes entries selected by a given block.

  • #shift: Removes and returns the first entry.

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

  • #compact: Returns a copy of self with all nil-valued entries removed.

  • #except: Returns a copy of self with entries removed for specified keys.

  • #select (aliased as #filter): Returns a copy of self with only those entries selected by a given block.

  • #reject: Returns a copy of self with entries removed as specified by a given block.

  • #slice: Returns a hash containing the entries for given keys.

Methods for Iterating

  • #each_pair (aliased as #each): Calls a given block with each key-value pair.

  • #each_key: Calls a given block with each key.

  • #each_value: Calls a given block with each value.

Methods for Converting

  • #inspect (aliased as #to_s): Returns a new String containing the hash entries.

  • #to_a: Returns a new array of 2-element arrays; each nested array contains a key-value pair from self.

  • #to_h: Returns self if a Hash; if a subclass of Hash, returns a Hash containing the entries from self.

  • #to_hash: Returns self.

  • #to_proc: Returns a proc that maps a given key to its value.

Methods for Transforming Keys and Values

  • #transform_keys: Returns a copy of self with modified keys.

  • #transform_keys!: Modifies keys in self

  • #transform_values: Returns a copy of self with modified values.

  • #transform_values!: Modifies values in self.

Other Methods

  • #flatten: Returns an array that is a 1-dimensional flattening of self.

  • #invert: Returns a hash with the each key-value pair inverted.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#all?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter_map, #find, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #inject, #lazy, #map, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reverse_each, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #uniq, #zip

Class Method Details

.HashObject .[](hash) ⇒ Object .[]([*2_element_arrays)) ⇒ Object .[](*objects) ⇒ Object

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

With no argument, returns a new empty Hash.

When the single given argument is a Hash, returns a new Hash populated with the entries from the given Hash, excluding the default value or proc.

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

When the single given argument is an Array of 2-element Arrays, returns a new Hash object wherein each 2-element array forms a key-value entry:

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

When the argument count is an even number; returns a new Hash object wherein each successive pair of arguments has become a key-value entry:

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

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



1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
# File 'hash.c', line 1826

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

.ruby2_keywords_hash(hash) ⇒ Hash

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

Returns:



1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
# File 'hash.c', line 1957

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) ⇒ Boolean

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

Returns:

  • (Boolean)


1935
1936
1937
1938
1939
1940
# File 'hash.c', line 1935

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(obj) ⇒ Object?

If obj is a Hash object, returns obj.

Otherwise if obj responds to :to_hash, calls obj.to_hash and returns the result.

Returns nil if obj does not respond to :to_hash

Raises an exception unless obj.to_hash returns a Hash object.

Returns:



1914
1915
1916
1917
1918
# File 'hash.c', line 1914

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

Instance Method Details

#<(other_hash) ⇒ Boolean

Returns true if hash is a proper subset of other_hash, false otherwise:

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

Returns:

  • (Boolean)


4663
4664
4665
4666
4667
4668
4669
# File 'hash.c', line 4663

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

#<=(other_hash) ⇒ Boolean

Returns true if hash is a subset of other_hash, false otherwise:

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

Returns:

  • (Boolean)


4644
4645
4646
4647
4648
4649
4650
# File 'hash.c', line 4644

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

#==(object) ⇒ Boolean

Returns true if all of the following are true:

  • object is a Hash object.

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

  • For each key key, hash[key] == object[key].

Otherwise, returns false.

Equal:

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

Returns:

  • (Boolean)


3822
3823
3824
3825
3826
# File 'hash.c', line 3822

static VALUE
rb_hash_equal(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, FALSE);
}

#>(other_hash) ⇒ Boolean

Returns true if hash is a proper superset of other_hash, false otherwise:

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

Returns:

  • (Boolean)


4701
4702
4703
4704
4705
4706
4707
# File 'hash.c', line 4701

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

#>=(other_hash) ⇒ Boolean

Returns true if hash is a superset of other_hash, false otherwise:

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

Returns:

  • (Boolean)


4682
4683
4684
4685
4686
4687
4688
# File 'hash.c', line 4682

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

#[](key) ⇒ Object

Returns the value associated with the given key, if found:

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

If key is not found, returns a default value (see Default Values):

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


2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
# File 'hash.c', line 2104

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

#[]=Object

#any?Boolean #any?(object) ⇒ Boolean #any? {|key, value| ... } ⇒ Boolean

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.

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

With argument object and no block, returns true if for any key key h.assoc(key) == object:

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

With no argument and a block, calls the block with each key-value pair; returns true if the block returns any 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

Related: Enumerable#any?

Overloads:

  • #any?Boolean

    Returns:

    • (Boolean)
  • #any?(object) ⇒ Boolean

    Returns:

    • (Boolean)
  • #any? {|key, value| ... } ⇒ Boolean

    Yields:

    Returns:

    • (Boolean)


4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
# File 'hash.c', line 4545

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) ⇒ nil

If the given key is found, returns 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 key key is not found.

Returns:

  • (nil)


4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
# File 'hash.c', line 4169

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

#clearself

Removes all hash entries; returns self.

Returns:

  • (self)


2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
# File 'hash.c', line 2851

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

#compactObject

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

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


4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
# File 'hash.c', line 4336

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?

Returns self with all its nil-valued entries removed (in place):

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

Returns nil if no entries were removed.

Returns:

  • (self, nil)


4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
# File 'hash.c', line 4361

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_identityself

Sets self to consider only identity in comparing keys; two keys are considered the same only if they are the same object; returns self.

By default, these two object are considered to be the same key, so s1 will overwrite s0:

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

After calling #compare_by_identity, the keys are considered to be different, and therefore do not overwrite each other:

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

Returns:

  • (self)


4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
# File 'hash.c', line 4403

VALUE
rb_hash_compare_by_id(VALUE hash)
{
    VALUE tmp;
    st_table *identtable;

    if (rb_hash_compare_by_id_p(hash)) return hash;

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

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

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

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

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

    return hash;
}

#compare_by_identity?Boolean

Returns true if #compare_by_identity has been called, false otherwise.

Returns:

  • (Boolean)


4450
4451
4452
4453
4454
# File 'hash.c', line 4450

VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    return RBOOL(RHASH_IDENTHASH_P(hash));
}

#deconstruct_keys(keys) ⇒ Object

:nodoc:



4735
4736
4737
4738
4739
# File 'hash.c', line 4735

static VALUE
rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
{
    return hash;
}

#defaultObject #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 Default Values.

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"

Overloads:



2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
# File 'hash.c', line 2221

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

Sets the default value to value; returns value:

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

See Default Values.

Returns:



2248
2249
2250
2251
2252
2253
2254
# File 'hash.c', line 2248

static VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
    rb_hash_modify_check(hash);
    SET_DEFAULT(hash, ifnone);
    return ifnone;
}

#default_procProc?

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

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

Returns:



2268
2269
2270
2271
2272
2273
2274
2275
# File 'hash.c', line 2268

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

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

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

Returns:



2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
# File 'hash.c', line 2291

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) ⇒ nil #delete(key) {|key| ... } ⇒ Object

Deletes the entry for the given key and returns its associated value.

If no block is given and key is found, deletes the entry and returns the associated value:

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

If no block given and key is not found, returns nil.

If a block is given and key is found, ignores the block, deletes the entry, and returns the associated value:

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

If a block is given and key is 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}

Overloads:

  • #delete(key) ⇒ nil

    Returns:

    • (nil)
  • #delete(key) {|key| ... } ⇒ Object

    Yields:

    Returns:



2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
# File 'hash.c', line 2424

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 #delete_ifObject

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

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

If no block given, returns a new Enumerator:

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

Overloads:

  • #delete_if {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)


2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
# File 'hash.c', line 2547

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

Finds and returns the object in nested objects that is 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

This method will use the default values for keys that are not present:

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

Returns:



4603
4604
4605
4606
4607
4608
4609
4610
4611
# File 'hash.c', line 4603

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 {|key, value| ... } ⇒ self #each_pair {|key, value| ... } ⇒ self #eachObject #each_pairObject

Calls the given 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

Returns a new Enumerator if no block given:

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

Output:

foo: 0
bar: 1
baz: 2

Overloads:

  • #each {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)
  • #each_pair {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)


3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
# File 'hash.c', line 3132

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

#each_key {|key| ... } ⇒ self #each_keyObject

Calls the given 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

Returns a new Enumerator if no block given:

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

Output:

foo
bar
baz

Overloads:

  • #each_key {|key| ... } ⇒ self

    Yields:

    Returns:

    • (self)


3081
3082
3083
3084
3085
3086
3087
# File 'hash.c', line 3081

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 {|key, value| ... } ⇒ self #each_pair {|key, value| ... } ⇒ self #eachObject #each_pairObject

Calls the given 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

Returns a new Enumerator if no block given:

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

Output:

foo: 0
bar: 1
baz: 2

Overloads:

  • #each {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)
  • #each_pair {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)


3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
# File 'hash.c', line 3132

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

#each_value {|value| ... } ⇒ self #each_valueObject

Calls the given 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

Returns a new Enumerator if no block given:

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

Output:

0
1
2

Overloads:

  • #each_value {|value| ... } ⇒ self

    Yields:

    • (value)

    Returns:

    • (self)


3043
3044
3045
3046
3047
3048
3049
# File 'hash.c', line 3043

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?Boolean

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

{}.empty? # => true
{foo: 0, bar: 1, baz: 2}.empty? # => false

Returns:

  • (Boolean)


3006
3007
3008
3009
3010
# File 'hash.c', line 3006

VALUE
rb_hash_empty_p(VALUE hash)
{
    return RBOOL(RHASH_EMPTY_P(hash));
}

#eql?(object) ⇒ Boolean

Returns true if all of the following are true:

  • object is a Hash object.

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

  • For each key key, h[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

Returns:

  • (Boolean)


3846
3847
3848
3849
3850
# File 'hash.c', line 3846

static VALUE
rb_hash_eql(VALUE hash1, VALUE hash2)
{
    return hash_equal(hash1, hash2, TRUE);
}

#except(*keys) ⇒ Hash

Returns a new Hash excluding entries for the given keys:

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

Any given keys that are not found are ignored.

Returns:



2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
# File 'hash.c', line 2666

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 #fetch(key, default_value) ⇒ Object #fetch(key) {|key| ... } ⇒ Object

Returns the value for the given key, if found.

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

If key is not found and no block was given, returns default_value:

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

If key is not found and a block was given, yields key to the block and returns the block’s return value:

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

Raises KeyError if neither default_value nor a block was given.

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

Overloads:



2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
# File 'hash.c', line 2159

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) ⇒ Object #fetch_values(*keys) {|key| ... } ⇒ Object

Returns a new Array containing the values associated with the given keys *keys:

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

Returns a new empty Array if no arguments given.

When a block is given, calls the block with each missing key, treating the block’s return value as the value for that key:

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

When no block is given, raises an exception if any given key is not found.

Overloads:

  • #fetch_values(*keys) {|key| ... } ⇒ Object

    Yields:



2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
# File 'hash.c', line 2728

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

#select {|key, value| ... } ⇒ Object #selectObject

Returns a new Hash object 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}

Returns a new Enumerator if no block given:

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

Overloads:

  • #select {|key, value| ... } ⇒ Object

    Yields:



2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
# File 'hash.c', line 2765

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

#select! {|key, value| ... } ⇒ self? #select!Object

Returns self, 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}

Returns nil if no entries were removed.

Returns a new Enumerator if no block given:

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

Overloads:

  • #select! {|key, value| ... } ⇒ self?

    Yields:

    Returns:

    • (self, nil)


2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
# File 'hash.c', line 2796

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

#flattenObject #flatten(level) ⇒ Object

Returns a new Array object that is a 1-dimensional flattening of self.


By default, nested Arrays are not flattened:

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

Takes the depth of recursive flattening from Integer argument level:

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

When level is negative, flattens all nested Arrays:

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

When level is zero, returns the equivalent of #to_a :

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


4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
# File 'hash.c', line 4284

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

#freezeObject

:nodoc:



107
108
109
110
111
# File 'hash.c', line 107

VALUE
rb_hash_freeze(VALUE hash)
{
    return rb_obj_freeze(hash);
}

#include?(key) ⇒ Boolean #has_key?(key) ⇒ Boolean #key?(key) ⇒ Boolean #member?(key) ⇒ Boolean

Returns true if key is a key in self, otherwise false.

Overloads:

  • #include?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #has_key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(key) ⇒ Boolean

    Returns:

    • (Boolean)


3685
3686
3687
3688
3689
# File 'hash.c', line 3685

VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

#has_value?(value) ⇒ Boolean #value?(value) ⇒ Boolean

Returns true if value is a value in self, otherwise false.

Overloads:

  • #has_value?(value) ⇒ Boolean

    Returns:

    • (Boolean)
  • #value?(value) ⇒ Boolean

    Returns:

    • (Boolean)


3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
# File 'hash.c', line 3711

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

#hashInteger

Returns the Integer hash-code for the hash.

Two Hash objects 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

Returns:



3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
# File 'hash.c', line 3878

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) ⇒ Boolean #has_key?(key) ⇒ Boolean #key?(key) ⇒ Boolean #member?(key) ⇒ Boolean

Returns true if key is a key in self, otherwise false.

Overloads:

  • #include?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #has_key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(key) ⇒ Boolean

    Returns:

    • (Boolean)


3685
3686
3687
3688
3689
# File 'hash.c', line 3685

VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

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

Returns:

  • (self)


2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
# File 'hash.c', line 2950

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

#inspectObject Also known as: 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}"


3497
3498
3499
3500
3501
3502
3503
# File 'hash.c', line 3497

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

#invertObject

Returns a new Hash object with the 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}


3913
3914
3915
3916
3917
3918
3919
3920
# File 'hash.c', line 3913

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 #keep_ifObject

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}

Returns a new Enumerator if no block given:

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

Overloads:

  • #keep_if {|key, value| ... } ⇒ self

    Yields:

    Returns:

    • (self)


2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
# File 'hash.c', line 2827

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) ⇒ nil

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.

Returns:

  • (nil)


2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
# File 'hash.c', line 2337

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

#include?(key) ⇒ Boolean #has_key?(key) ⇒ Boolean #key?(key) ⇒ Boolean #member?(key) ⇒ Boolean

Returns true if key is a key in self, otherwise false.

Overloads:

  • #include?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #has_key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(key) ⇒ Boolean

    Returns:

    • (Boolean)


3685
3686
3687
3688
3689
# File 'hash.c', line 3685

VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

#keysObject

Returns a new Array containing all keys in self:

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


3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
# File 'hash.c', line 3598

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

#lengthInteger #sizeInteger

Returns the count of entries in self:

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

Overloads:



2985
2986
2987
2988
2989
# File 'hash.c', line 2985

VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}

#include?(key) ⇒ Boolean #has_key?(key) ⇒ Boolean #key?(key) ⇒ Boolean #member?(key) ⇒ Boolean

Returns true if key is a key in self, otherwise false.

Overloads:

  • #include?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #has_key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #key?(key) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(key) ⇒ Boolean

    Returns:

    • (Boolean)


3685
3686
3687
3688
3689
# File 'hash.c', line 3685

VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    return RBOOL(hash_stlike_lookup(hash, key, NULL));
}

#mergeObject #merge(*other_hashes) ⇒ Object #merge(*other_hashes) {|key, old_value, new_value| ... } ⇒ Object

Returns the new Hash formed by merging each of other_hashes into a copy of self.

Each argument in other_hashes must be a Hash.


With arguments and no block:

  • Returns the new Hash object formed by merging each successive Hash in other_hashes into self.

  • Each new-key entry is added at the end.

  • Each duplicate-key entry’s value overwrites the previous value.

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 and a block:

  • Returns a new Hash object that is the merge of self and each given hash.

  • The given hashes are merged left to right.

  • Each new-key entry is added at the end.

  • For each duplicate key:

    • Calls the block with the key and the old and new values.

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

Example:

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

With no arguments:

  • Returns a copy of self.

  • The block, if given, is ignored.

Example:

h = {foo: 0, bar: 1, baz: 2}
h.merge # => {:foo=>0, :bar=>1, :baz=>2}
h1 = h.merge { |key, old_value, new_value| raise 'Cannot happen' }
h1 # => {:foo=>0, :bar=>1, :baz=>2}

Overloads:

  • #merge(*other_hashes) {|key, old_value, new_value| ... } ⇒ Object

    Yields:

    • (key, old_value, new_value)


4120
4121
4122
4123
4124
# File 'hash.c', line 4120

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!self #merge!(*other_hashes) ⇒ self #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self

Merges each of other_hashes into self; returns self.

Each argument in other_hashes must be a Hash.

With arguments and no block:

  • Returns self, after the given hashes are merged into it.

  • The given hashes are merged left to right.

  • Each new entry is added at the end.

  • Each duplicate-key entry’s value overwrites the previous value.

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 and a block:

  • Returns self, after the given hashes are merged.

  • The given hashes are merged left to right.

  • Each new-key entry is added at the end.

  • For each duplicate key:

    • Calls the block with the key and the old and new values.

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

Example:

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

With no arguments:

  • Returns self, unmodified.

  • The block, if given, is ignored.

Example:

h = {foo: 0, bar: 1, baz: 2}
h.merge # => {:foo=>0, :bar=>1, :baz=>2}
h1 = h.merge! { |key, old_value, new_value| raise 'Cannot happen' }
h1 # => {:foo=>0, :bar=>1, :baz=>2}

Overloads:

  • #merge!self

    Returns:

    • (self)
  • #merge!(*other_hashes) ⇒ self

    Returns:

    • (self)
  • #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self

    Yields:

    • (key, old_value, new_value)

    Returns:

    • (self)


4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
# File 'hash.c', line 4001

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

#rassoc(value) ⇒ nil

Returns a new 2-element Array consisting of the key and value of the first-found entry whose value is == to value (see Entry Order):

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

Returns nil if no such value found.

Returns:

  • (nil)


4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
# File 'hash.c', line 4230

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

#rehashself

Rebuilds the hash table by recomputing the hash index for each key; returns self.

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.

Returns:

  • (self)


1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
# File 'hash.c', line 1998

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| ... } ⇒ Object #rejectObject

Returns a new Hash object whose entries are all those from self for which the block returns false or nil:

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

Returns a new Enumerator if no block given:

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

Overloads:

  • #reject {|key, value| ... } ⇒ Object

    Yields:



2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
# File 'hash.c', line 2609

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? #reject!Object

Returns self, whose remaining entries are those for which the block returns false or nil:

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

Returns nil if no entries are removed.

Returns a new Enumerator if no block given:

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

Overloads:

  • #reject! {|key, value| ... } ⇒ self?

    Yields:

    Returns:

    • (self, nil)


2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
# File 'hash.c', line 2577

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}

Returns:

  • (self)


2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
# File 'hash.c', line 2950

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

#select {|key, value| ... } ⇒ Object #selectObject

Returns a new Hash object 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}

Returns a new Enumerator if no block given:

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

Overloads:

  • #select {|key, value| ... } ⇒ Object

    Yields:



2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
# File 'hash.c', line 2765

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

#select! {|key, value| ... } ⇒ self? #select!Object

Returns self, 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}

Returns nil if no entries were removed.

Returns a new Enumerator if no block given:

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

Overloads:

  • #select! {|key, value| ... } ⇒ self?

    Yields:

    Returns:

    • (self, nil)


2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
# File 'hash.c', line 2796

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

#shiftArray?

Removes the first hash entry (see Entry Order); returns a 2-element Array containing the removed key and value:

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

Returns nil if the hash is empty.

Returns:



2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
# File 'hash.c', line 2475

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

#lengthInteger #sizeInteger

Returns the count of entries in self:

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

Overloads:



2985
2986
2987
2988
2989
# File 'hash.c', line 2985

VALUE
rb_hash_size(VALUE hash)
{
    return INT2FIX(RHASH_SIZE(hash));
}

#slice(*keys) ⇒ Object

Returns a new Hash object containing the entries for the given keys:

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

Any given keys that are not found are ignored.



2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
# File 'hash.c', line 2634

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

#storeObject

#to_aObject

Returns a new Array of 2-element Array objects; 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]]


3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
# File 'hash.c', line 3397

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_hself #to_h {|key, value| ... } ⇒ Object

For an instance of Hash, returns self.

For a subclass of Hash, returns a new Hash containing the content of self.

When a block is given, returns a new Hash object whose content is based on the block; the block should return a 2-element Array object specifying the key-value pair to be included in the returned Array:

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

Overloads:

  • #to_hself

    Returns:

    • (self)
  • #to_h {|key, value| ... } ⇒ Object

    Yields:



3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
# File 'hash.c', line 3569

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_hashself

Returns self.

Returns:

  • (self)


3511
3512
3513
3514
3515
# File 'hash.c', line 3511

static VALUE
rb_hash_to_hash(VALUE hash)
{
    return hash;
}

#to_procProc

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

Returns:



4728
4729
4730
4731
4732
# File 'hash.c', line 4728

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

#transform_keys {|key| ... } ⇒ Object #transform_keys(hash2) ⇒ Object #transform_keys(hash2) {|other_key| ... } ⇒ Object #transform_keysObject

Returns a new Hash object; each entry has:

  • A key provided by the block.

  • The value from self.

An optional hash argument can be provided to map keys to new keys. Any key not given will be mapped using the provided block, or remain the same if no block is given.

Transform keys:

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

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

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

Overwrites values for duplicate keys:

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

Returns a new Enumerator if no block given:

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

Overloads:

  • #transform_keys {|key| ... } ⇒ Object

    Yields:

  • #transform_keys(hash2) {|other_key| ... } ⇒ Object

    Yields:

    • (other_key)


3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
# File 'hash.c', line 3210

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! {|key| ... } ⇒ self #transform_keys!(hash2) ⇒ self #transform_keys!(hash2) {|other_key| ... } ⇒ self #transform_keys!Object

Same as Hash#transform_keys but modifies the receiver in place instead of returning a new hash.

Overloads:

  • #transform_keys! {|key| ... } ⇒ self

    Yields:

    Returns:

    • (self)
  • #transform_keys!(hash2) ⇒ self

    Returns:

    • (self)
  • #transform_keys!(hash2) {|other_key| ... } ⇒ self

    Yields:

    • (other_key)

    Returns:

    • (self)


3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
# File 'hash.c', line 3250

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| ... } ⇒ Object #transform_valuesObject

Returns a new Hash object; each entry has:

  • A key from self.

  • A value provided by the block.

Transform values:

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

Returns a new Enumerator if no block given:

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

Overloads:

  • #transform_values {|value| ... } ⇒ Object

    Yields:

    • (value)


3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
# File 'hash.c', line 3335

static VALUE
rb_hash_transform_values(VALUE hash)
{
    VALUE result;

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

    if (!RHASH_EMPTY_P(hash)) {
        rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, result);
        compact_after_delete(result);
    }

    return result;
}

#transform_values! {|value| ... } ⇒ self #transform_values!Object

Returns self, whose keys are unchanged, and whose values are determined by the given block.

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

Returns a new Enumerator if no block given:

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

Overloads:

  • #transform_values! {|value| ... } ⇒ self

    Yields:

    • (value)

    Returns:

    • (self)


3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
# File 'hash.c', line 3367

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

#merge!self #merge!(*other_hashes) ⇒ self #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self

Merges each of other_hashes into self; returns self.

Each argument in other_hashes must be a Hash.

With arguments and no block:

  • Returns self, after the given hashes are merged into it.

  • The given hashes are merged left to right.

  • Each new entry is added at the end.

  • Each duplicate-key entry’s value overwrites the previous value.

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 and a block:

  • Returns self, after the given hashes are merged.

  • The given hashes are merged left to right.

  • Each new-key entry is added at the end.

  • For each duplicate key:

    • Calls the block with the key and the old and new values.

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

Example:

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

With no arguments:

  • Returns self, unmodified.

  • The block, if given, is ignored.

Example:

h = {foo: 0, bar: 1, baz: 2}
h.merge # => {:foo=>0, :bar=>1, :baz=>2}
h1 = h.merge! { |key, old_value, new_value| raise 'Cannot happen' }
h1 # => {:foo=>0, :bar=>1, :baz=>2}

Overloads:

  • #merge!self

    Returns:

    • (self)
  • #merge!(*other_hashes) ⇒ self

    Returns:

    • (self)
  • #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self

    Yields:

    • (key, old_value, new_value)

    Returns:

    • (self)


4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
# File 'hash.c', line 4001

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

#has_value?(value) ⇒ Boolean #value?(value) ⇒ Boolean

Returns true if value is a value in self, otherwise false.

Overloads:

  • #has_value?(value) ⇒ Boolean

    Returns:

    • (Boolean)
  • #value?(value) ⇒ Boolean

    Returns:

    • (Boolean)


3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
# File 'hash.c', line 3711

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

#valuesObject

Returns a new Array containing all values in self:

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


3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
# File 'hash.c', line 3642

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) ⇒ Object

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 default values are returned for any keys that are not found:

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


2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
# File 'hash.c', line 2696

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