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 useable 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?: Returns whether a given object is a value in self.

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

  • #length, #size: Returns the count of entries.

  • #value?: Returns whether a given object is a value in self.

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

  • #[]=, #store: Associates a given key with a given value.

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

  • #merge!, #update: Merges each given hash into self.

  • #replace: 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.

  • #filter!, #select!: 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.

  • #filter, #select: 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, #each_pair: 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, #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

Constructor Details

#new(default_value = nil) ⇒ Object #new {|hash, key| ... } ⇒ Object

Returns a new empty Hash object.

The initial default value and initial default proc for the new hash depend on which form above was used. See Default Values.

If neither an argument nor a block given, initializes both the default value and the default proc to nil:

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

If argument default_value given but no block given, initializes the default value to the given default_value and the default proc to nil:

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

If a block given but no argument, stores the block as the default proc and sets the default value to nil:

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

Overloads:



1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
# File 'hash.c', line 1779

static VALUE
rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
{
    rb_hash_modify(hash);

    if (rb_block_given_p()) {
        rb_check_arity(argc, 0, 0);
        SET_PROC_DEFAULT(hash, rb_block_proc());
    }
    else {
        rb_check_arity(argc, 0, 1);

        VALUE options, ifnone;
        rb_scan_args(argc, argv, "01:", &ifnone, &options);
        if (NIL_P(ifnone) && !NIL_P(options)) {
            ifnone = options;
            rb_warn_deprecated_to_remove("3.4", "Calling Hash.new with keyword arguments", "Hash.new({ key: value })");
        }
        RHASH_SET_IFNONE(hash, ifnone);
    }

    return hash;
}

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.



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
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
# File 'hash.c', line 1840

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:



1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
# File 'hash.c', line 1971

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)


1949
1950
1951
1952
1953
1954
# File 'hash.c', line 1949

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:



1928
1929
1930
1931
1932
# File 'hash.c', line 1928

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)


4633
4634
4635
4636
4637
4638
4639
# File 'hash.c', line 4633

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)


4614
4615
4616
4617
4618
4619
4620
# File 'hash.c', line 4614

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)


3791
3792
3793
3794
3795
# File 'hash.c', line 3791

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)


4671
4672
4673
4674
4675
4676
4677
# File 'hash.c', line 4671

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)


4652
4653
4654
4655
4656
4657
4658
# File 'hash.c', line 4652

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


2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
# File 'hash.c', line 2118

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)


4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
# File 'hash.c', line 4515

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)


4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
# File 'hash.c', line 4139

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)


2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
# File 'hash.c', line 2865

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}


4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
# File 'hash.c', line 4306

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)


4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
# File 'hash.c', line 4331

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)


4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
# File 'hash.c', line 4373

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)


4420
4421
4422
4423
4424
# File 'hash.c', line 4420

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

#deconstruct_keys(keys) ⇒ Object

:nodoc:



4705
4706
4707
4708
4709
# File 'hash.c', line 4705

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:



2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
# File 'hash.c', line 2235

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:



2262
2263
2264
2265
2266
2267
2268
# File 'hash.c', line 2262

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:



2282
2283
2284
2285
2286
2287
2288
2289
# File 'hash.c', line 2282

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:



2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
# File 'hash.c', line 2305

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:



2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
# File 'hash.c', line 2438

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)


2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
# File 'hash.c', line 2561

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:



4573
4574
4575
4576
4577
4578
4579
4580
4581
# File 'hash.c', line 4573

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)


3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
# File 'hash.c', line 3146

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)


3095
3096
3097
3098
3099
3100
3101
# File 'hash.c', line 3095

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)


3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
# File 'hash.c', line 3146

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)


3057
3058
3059
3060
3061
3062
3063
# File 'hash.c', line 3057

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)


3020
3021
3022
3023
3024
# File 'hash.c', line 3020

static 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.

Equal:

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)


3816
3817
3818
3819
3820
# File 'hash.c', line 3816

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:



2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
# File 'hash.c', line 2680

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:



2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
# File 'hash.c', line 2173

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:



2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
# File 'hash.c', line 2742

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:



2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
# File 'hash.c', line 2779

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)


2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
# File 'hash.c', line 2810

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


4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
# File 'hash.c', line 4254

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

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


3654
3655
3656
3657
3658
# File 'hash.c', line 3654

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)


3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
# File 'hash.c', line 3680

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:



3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
# File 'hash.c', line 3848

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)


3654
3655
3656
3657
3658
# File 'hash.c', line 3654

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)


2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
# File 'hash.c', line 2964

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


3466
3467
3468
3469
3470
3471
3472
# File 'hash.c', line 3466

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}


3883
3884
3885
3886
3887
3888
3889
3890
# File 'hash.c', line 3883

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)


2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
# File 'hash.c', line 2841

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)


2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
# File 'hash.c', line 2351

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)


3654
3655
3656
3657
3658
# File 'hash.c', line 3654

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]


3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
# File 'hash.c', line 3567

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:



2999
3000
3001
3002
3003
# File 'hash.c', line 2999

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)


3654
3655
3656
3657
3658
# File 'hash.c', line 3654

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)


4090
4091
4092
4093
4094
# File 'hash.c', line 4090

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)


3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
# File 'hash.c', line 3971

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)


4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
# File 'hash.c', line 4200

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)


2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
# File 'hash.c', line 2012

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:



2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
# File 'hash.c', line 2623

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)


2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
# File 'hash.c', line 2591

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)


2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
# File 'hash.c', line 2964

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:



2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
# File 'hash.c', line 2779

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)


2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
# File 'hash.c', line 2810

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:



2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
# File 'hash.c', line 2489

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:



2999
3000
3001
3002
3003
# File 'hash.c', line 2999

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.



2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
# File 'hash.c', line 2648

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


3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
# File 'hash.c', line 3411

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:



3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
# File 'hash.c', line 3538

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)


3480
3481
3482
3483
3484
# File 'hash.c', line 3480

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:



4698
4699
4700
4701
4702
# File 'hash.c', line 4698

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)


3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
# File 'hash.c', line 3224

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)


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
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
# File 'hash.c', line 3264

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)


3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
# File 'hash.c', line 3349

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)


3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
# File 'hash.c', line 3381

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)


3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
# File 'hash.c', line 3971

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)


3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
# File 'hash.c', line 3680

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]


3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
# File 'hash.c', line 3611

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]


2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
# File 'hash.c', line 2710

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