123456789_123456789_123456789_123456789_123456789_

Class: Hash

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, ::Enumerable
Inherits: Object
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'}

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

Here are three ways to create a Hash:

  • Method .new

  • Method Hash[]

  • Literal form: {}.


You can create a Hash by calling method .new.

Create an empty Hash:

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

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

Create an empty Hash:

h = Hash[]
h # => {}

Create a Hash with initial entries:

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

You can create a Hash by using its literal form (curly braces).

Create an empty Hash:

h = {}
h # => {}

Create a Hash with initial entries:

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

Hash Value Basics

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

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

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

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

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

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

Entry Order

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

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

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

New entries are added at the end:

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

Updating a value does not affect the order:

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

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

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

Hash Keys

Hash Key Equivalence

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

Invalid Hash Keys

An object that lacks method #hash cannot be a Hash key:

# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
{BasicObject.new => 0}

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
first_key.equal?(s) # => false

User-Defined Hash Keys

A user-defined class may be used as a Hash key if the #hash and #eql? methods are overridden to provide meaningful behavior. By default, separate instances refer to separate Hash keys.

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 and
      other.author == @author and
      other.title == @title
  end

  alias eql? ==

  def hash
    @author.hash ^ @title.hash # XOR
  end
end

book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'

reviews = {}

reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'

reviews.length #=> 1

Default Values

For a key that is not found, method #[] returns a default value determined by:

  • Its default proc, if the default proc is not nil.

  • Its default value, otherwise.

Default Value

A Hash object's default value is relevant only when its default proc is nil. (Initially, both are nil).

You can retrieve the default value with method #default:

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

You can initialize the default value by passing an argument to method .new:

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

You can update the default value with method #default=:

h.default = false
h.default # => false

Incidentally, updating the default value (even to nil) also sets the default proc to nil:

h.default_proc = proc { }
h.default = nil
h.default_proc # => nil

When the default proc is nil, method #[] returns the value of method #default:

h = Hash.new
h.default_proc # => nil
h.default # => nil
h[:nosuch] # => nil
h.default = false
h[:nosuch] # => false

For certain kinds of default values, the default value can be modified thus:

h = Hash.new('Foo')
h[:nosuch] # => "Foo"
h[:nosuch].upcase! # => "FOO"
h[:nosuch] # => "FOO"
h.default = [0, 1]
h[:nosuch] # => [0, 1]
h[:nosuch].reverse! # => [1, 0]
h[:nosuch] # => [1, 0]

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 initialize the default proc by calling .new with a block:

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

You can update the default proc with method #default_proc=:

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

Incidentally, updating the default proc (even to nil) also sets the default value to nil:

h.default = false
h.default_proc = nil
h.default # => nil

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:

h = Hash.new { |hash, key| hash[key] = "Subsequent value for #{key}"; "First value for #{key}" }
h.include?(:nosuch) # => false
h[:nosuch] # => "First value for nosuch"
h.include?(:nosuch) # => true
h[:nosuch] # => "Subsequent value for nosuch"
h[:nosuch] # => "Subsequent value for nosuch"

You can set the default proc to nil, which restores control to the default value:

h.delete(:nosuch)
h.default_proc = nil
h.default = false
h[:nosuch] # => false

Class Method Summary

Instance Attribute Summary

Instance Method Summary

::Enumerable - Included

#all?

Passes each element of the collection to the given block.

#any?

Passes each element of the collection to the given block.

#chain

Returns an enumerator object generated from this enumerator and given enumerables.

#chunk

Enumerates over the items, chunking them together based on the return value of the block.

#chunk_while

Creates an enumerator for each chunked elements.

#collect

Alias for Enumerable#map.

#collect_concat
#count

Returns the number of items in enum through enumeration.

#cycle

Calls block for each element of enum repeatedly n times or forever if none or nil is given.

#detect

Alias for Enumerable#find.

#drop

Drops first n elements from enum, and returns rest elements in an array.

#drop_while

Drops elements up to, but not including, the first element for which the block returns nil or false and returns an array containing the remaining elements.

#each_cons

Iterates the given block for each array of consecutive <n> elements.

#each_entry

Calls block once for each element in self, passing that element as a parameter, converting multiple values from yield to an array.

#each_slice

Iterates the given block for each slice of <n> elements.

#each_with_index

Calls block with two arguments, the item and its index, for each item in enum.

#each_with_object

Iterates the given block for each element with an arbitrary object given, and returns the initially given object.

#entries

Alias for Enumerable#to_a.

#filter

Returns an array containing all elements of enum for which the given block returns a true value.

#filter_map

Returns a new array containing the truthy results (everything except false or nil) of running the block for every element in enum.

#find

Passes each entry in enum to block.

#find_all
#find_index

Compares each entry in enum with value or passes to block.

#first

Returns the first element, or the first n elements, of the enumerable.

#flat_map

Returns a new array with the concatenated results of running block once for every element in enum.

#grep

Returns an array of every element in enum for which Pattern === element.

#grep_v

Inverted version of Enumerable#grep.

#group_by

Groups the collection by result of the block.

#include?
#inject

Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.

#lazy

Returns an ::Enumerator::Lazy, which redefines most ::Enumerable methods to postpone enumeration and enumerate values only on an as-needed basis.

#map

Returns a new array with the results of running block once for every element in enum.

#max

Returns the object in enum with the maximum value.

#max_by

Returns the object in enum that gives the maximum value from the given block.

#member?

Returns true if any member of enum equals obj.

#min

Returns the object in enum with the minimum value.

#min_by

Returns the object in enum that gives the minimum value from the given block.

#minmax

Returns a two element array which contains the minimum and the maximum value in the enumerable.

#minmax_by

Returns a two element array containing the objects in enum that correspond to the minimum and maximum values respectively from the given block.

#none?

Passes each element of the collection to the given block.

#one?

Passes each element of the collection to the given block.

#partition

Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.

#reduce
#reject

Returns an array for all elements of enum for which the given block returns false.

#reverse_each

Builds a temporary array and traverses that array in reverse order.

#select
#slice_after

Creates an enumerator for each chunked elements.

#slice_before

Creates an enumerator for each chunked elements.

#slice_when

Creates an enumerator for each chunked elements.

#sort

Returns an array containing the items in enum sorted.

#sort_by

Sorts enum using a set of keys generated by mapping the values in enum through the given block.

#sum

Returns the sum of elements in an ::Enumerable.

#take

Returns first n elements from enum.

#take_while

Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements.

#tally

Tallies the collection, i.e., counts the occurrences of each element.

#to_a

Returns an array containing the items in enum.

#to_h

Returns the result of interpreting enum as a list of [key, value] pairs.

#uniq

Returns a new array by removing duplicate values in self.

#zip

Takes one element from enum and merges corresponding elements from each args.

Constructor Details

.newHash .new(default_value) ⇒ Hash .new {|hash, key| ... } ⇒ Hash

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 argument nor block given, initializes both the default value and the default proc to nil:

h = Hash.new
h # => {}
h.class # => Hash
h.default # => nil
h.default_proc # => nil
h[:nosuch] # => 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 # => {}
h.default # => false
h.default_proc # => nil
h[:nosuch] # => false

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

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

Raises an exception if both argument default_value and a block are given:

# Raises ArgumentError (wrong number of arguments (given 1, expected 0)):
Hash.new(0) { }
[ GitHub ]

  
# File 'hash.c', line 1797

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

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

    return hash;
}

Class Method Details

.[]Hash .[]([*2_element_arrays] ) ⇒ Hash .[](*objects) ⇒ Hash .[](hash_convertible_object) ⇒ Hash

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

The initial default value and default proc are set to nil (see Default Values):

h = Hash[]
h # => {}
h.class # => Hash
h.default # => nil
h.default_proc # => nil

When argument [*2_element_arrays] is given, each element of the outer array must be a 2-element array; 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 arguments *objects are given, the argument count must be an even number; returns a new Hash object wherein each successive pair of arguments has become a key-value entry:

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

When argument hash_convertible_object is given, the argument must be a Hash-convertible object; converts the object and returns the resulting Hash object:

class Foo
  def to_hash
    {foo: 0, bar: 1}
  end
end
Hash[Foo.new] # => {:foo=>0, :bar=>1}

Raises an exception if the argument count is 1, but the argument is not an array of 2-element arrays or a Hash-convertible object:

# Raises ArgumentError (odd number of arguments for Hash):
Hash[:foo]
# Raises ArgumentError (invalid number of elements (3 for 1..2)):
Hash[ [ [:foo, 0, 1] ] ]

Raises an exception if the argument count is odd and greater than 1:

# Raises ArgumentError (odd number of arguments for Hash):
Hash[0, 1, 2]

Raises an exception if the argument is an array containing an element that is not a 2-element array:

# Raises ArgumentError (wrong element type Symbol at 0 (expected array)):
Hash[ [ :foo ] ]

Raises an exception if the argument is an array containing an element that is an array of size different from 2:

# Raises ArgumentError (invalid number of elements (3 for 1..2)):
Hash[ [ [0, 1, 2] ] ]

Raises an exception if any proposed key is not a valid key (see Invalid Hash Keys):

# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
Hash[:foo, 0, BasicObject.new, 1]
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
Hash[ [ [:foo, 0], [BasicObject.new, 1] ] ]
[ GitHub ]

  
# File 'hash.c', line 1897

static VALUE
rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
{
    VALUE hash, tmp;

    if (argc == 1) {
        tmp = rb_hash_s_try_convert(Qnil, argv[0]);
	if (!NIL_P(tmp)) {
	    hash = hash_alloc(klass);
            hash_copy(hash, tmp);
	    return hash;
	}

	tmp = rb_check_array_type(argv[0]);
	if (!NIL_P(tmp)) {
	    long i;

	    hash = hash_alloc(klass);
	    for (i = 0; i < RARRAY_LEN(tmp); ++i) {
		VALUE e = RARRAY_AREF(tmp, i);
		VALUE v = rb_check_array_type(e);
		VALUE key, val = Qnil;

		if (NIL_P(v)) {
		    rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
			     rb_builtin_class_name(e), i);
		}
		switch (RARRAY_LEN(v)) {
		  default:
		    rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
			     RARRAY_LEN(v));
		  case 2:
		    val = RARRAY_AREF(v, 1);
		  case 1:
		    key = RARRAY_AREF(v, 0);
		    rb_hash_aset(hash, key, val);
		}
	    }
	    return hash;
	}
    }
    if (argc % 2 != 0) {
	rb_raise(rb_eArgError, "odd number of arguments for Hash");
    }

    hash = hash_alloc(klass);
    rb_hash_bulk_insert(argc, argv, hash);
    hash_verify(hash);
    return hash;
}

.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
[ GitHub ]

  
# File 'hash.c', line 2035

static VALUE
rb_hash_s_ruby2_keywords_hash(VALUE dummy, VALUE hash)
{
    Check_Type(hash, T_HASH);
    hash = rb_hash_dup(hash);
    RHASH(hash)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
    return hash;
}

.ruby2_keywords_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
[ GitHub ]

  
# File 'hash.c', line 2013

static VALUE
rb_hash_s_ruby2_keywords_hash_p(VALUE dummy, VALUE hash)
{
    Check_Type(hash, T_HASH);
    return (RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS) ? Qtrue : Qfalse;
}

.try_convert(obj) ⇒ Hash?

Returns the Hash object created by calling obj.to_hash:

require 'csv' # => true
row = CSV::Row.new(['Name', 'Age'], ['Bob', 45])
row.respond_to?(:to_hash)  # => true
Hash.try_convert(row) # => {"Name"=>"Bob", "Age"=>45}

Returns the given obj if it is a Hash:

h = {}
h1 = Hash.try_convert(h)
h1.equal?(h) # => true # Identity check

Returns nil unless obj.respond_to?(:to_hash):

s = 'foo'
s.respond_to?(:to_hash) # => false
Hash.try_convert(s) # => nil

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

class BadToHash
  def to_hash
    1
  end
end
bad = BadToHash.new
Hash.try_convert(bad) # Raises TypeError (can't convert BadToHash to Hash (BadToHash#to_hash gives Integer))
[ GitHub ]

  
# File 'hash.c', line 1992

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

Instance Attribute Details

#compare_by_identityHash (readonly)

Makes hsh compare its keys by their identity, i.e. it will consider exact same objects as same keys.

h1 = { "a" => 100, "b" => 200, :c => "c" }
h1["a"]        #=> 100
h1.compare_by_identity
h1.compare_by_identity? #=> true
h1["a".dup]    #=> nil  # different objects.
h1[:c]         #=> "c"  # same symbols are all same.
[ GitHub ]

  
# File 'hash.c', line 4728

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

    if (rb_hash_compare_by_id_p(hash)) return hash;

    rb_hash_modify_check(hash);
    ar_force_convert_table(hash, __FILE__, __LINE__);
    HASH_ASSERT(RHASH_ST_TABLE_P(hash));

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

    return hash;
}

#compare_by_identity?Boolean (readonly)

Returns true if hsh will compare its keys by their identity. Also see #compare_by_identity.

[ GitHub ]

  
# File 'hash.c', line 4761

MJIT_FUNC_EXPORTED VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    if (RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash) {
	return Qtrue;
    }
    else {
        return Qfalse;
    }
}

#default_procProc? (rw)

Returns the default proc:

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

See Default Values.

[ GitHub ]

  
# File 'hash.c', line 2361

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 (rw)

Sets the default proc to proc:

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

See Default Values.


Raises an exception if proc is not a Proc:

# Raises TypeError (wrong default_proc type Integer (expected Proc)):
h.default_proc = 1
[ GitHub ]

  
# File 'hash.c', line 2391

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

#empty?Boolean (readonly)

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

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

  
# File 'hash.c', line 3266

static VALUE
rb_hash_empty_p(VALUE hash)
{
    return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
}

Instance Method Details

#<(other) ⇒ Boolean

Returns true if hash is subset of other.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 < h2    #=> true
h2 < h1    #=> false
h1 < h1    #=> false
[ GitHub ]

  
# File 'hash.c', line 4945

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

Returns true if hash is subset of other or equals to other.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 <= h2   #=> true
h2 <= h1   #=> false
h1 <= h1   #=> true
[ GitHub ]

  
# File 'hash.c', line 4924

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

#==(other_hash) ⇒ Boolean

Equality—Two hashes are equal if they each contain the same number of keys and if each key-value pair is equal to (according to Object#==) the corresponding elements in the other hash.

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

The orders of each hashes are not compared.

h1 = { "a" => 1, "c" => 2 }
h2 = { "c" => 2, "a" => 1 }
h1 == h2   #=> true
[ GitHub ]

  
# File 'hash.c', line 4153

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

#>(other) ⇒ Boolean

Returns true if other is subset of hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 > h2    #=> false
h2 > h1    #=> true
h1 > h1    #=> false
[ GitHub ]

  
# File 'hash.c', line 4987

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

Returns true if other is subset of hash or equals to hash.

h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 >= h2   #=> false
h2 >= h1   #=> true
h1 >= h1   #=> true
[ GitHub ]

  
# File 'hash.c', line 4966

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

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

  
# File 'hash.c', line 2168

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

#[]=(key, value) ⇒ value #store(key, value)
Also known as: #store

Associates the given value with the given #key, and returns value.

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

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

If #key does not exist, adds the #key and value; the new entry is last in the order (see Entry Order):

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

Raises an exception if #key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h[BasicObject.new] = 2
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.store(BasicObject.new, 2)
[ GitHub ]

  
# File 'hash.c', line 3155

VALUE
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
    int iter_lev = RHASH_ITER_LEV(hash);

    rb_hash_modify(hash);

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

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

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

See also Enumerable#any?

[ GitHub ]

  
# File 'hash.c', line 4833

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

Searches through the hash comparing obj with the key using #==. Returns the key-value pair (two elements array) or nil if no match is found. See Array#assoc.

h = {"colors"  => ["red", "blue", "green"],
     "letters" => ["a", "b", "c" ]}
h.assoc("letters")  #=> ["letters", ["a", "b", "c"]]
h.assoc("foo")      #=> nil
[ GitHub ]

  
# File 'hash.c', line 4511

VALUE
rb_hash_assoc(VALUE hash, VALUE key)
{
    st_table *table;
    const struct st_hash_type *orighash;
    VALUE args[2];

    if (RHASH_EMPTY_P(hash)) return Qnil;

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

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

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

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

#clearself

Removes all hash entries; returns self:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.clear # => {}
h1.equal?(h) # => true # Identity check
[ GitHub ]

  
# File 'hash.c', line 3065

VALUE
rb_hash_clear(VALUE hash)
{
    rb_hash_modify_check(hash);

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

    return hash;
}

#compactHash

Returns a new hash with the nil values/key pairs removed

h = { a: 1, b: false, c: nil }
h.compact     #=> { a: 1, b: false }
h             #=> { a: 1, b: false, c: nil }
[ GitHub ]

  
# File 'hash.c', line 4674

static VALUE
rb_hash_compact(VALUE hash)
{
    VALUE result = rb_hash_new();
    if (!RHASH_EMPTY_P(hash)) {
	rb_hash_foreach(hash, set_if_not_nil, result);
    }
    return result;
}

#compact!Hash?

Removes all nil values from the hash. Returns nil if no changes were made, otherwise returns the hash.

h = { a: 1, b: false, c: nil }
h.compact!     #=> { a: 1, b: false }
[ GitHub ]

  
# File 'hash.c', line 4696

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

#deconstruct_keys(keys)

[ GitHub ]

  
# File 'hash.c', line 5021

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

#defaultvalue #default(key) ⇒ value

With no argument, returns the current default value:

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

With #key given, returns the default value for #key, regardless of whether that key exists:

h = {}
h.default(:nosuch) # => nil

The returned value will be determined either by the default proc or by the default value. See Default Values.

[ GitHub ]

  
# File 'hash.c', line 2313

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

Sets the default value to value, returning value:

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

See Default Values.

[ GitHub ]

  
# File 'hash.c', line 2340

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

#delete(key) ⇒ value? #delete(key) { |key| ... } -<value)

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:

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

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

Raises an exception if #key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.delete(BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 2547

static VALUE
rb_hash_delete_m(VALUE hash, VALUE key)
{
    VALUE val;

    rb_hash_modify_check(hash);
    val = rb_hash_delete_entry(hash, key);

    if (val != Qundef) {
	return val;
    }
    else {
	if (rb_block_given_p()) {
	    return rb_yield(key);
	}
	else {
	    return Qnil;
	}
    }
}

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

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}
h1 = h.delete_if { |key, value| value > 0 }
h1 # => {:foo=>0}
h1.equal?(h) # => true #  Identity check

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>
h1 = e.each { |key, value| value > 0 }
h1 # => {:foo=>0}
h1.equal?(h) # => true #  Identity check

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.delete_if { |key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 2682

VALUE
rb_hash_delete_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        rb_hash_foreach(hash, delete_if_i, hash);
    }
    return hash;
}

#dig(key, ...) ⇒ Object

Extracts the nested value specified by the sequence of key objects by calling dig at each step, returning nil if any intermediate step is nil.

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

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

g = { foo: [10, 11, 12] }
g.dig(:foo, 1)              #=> 11
g.dig(:foo, 1, 0)           #=> TypeError: Integer does not have #dig method
g.dig(:foo, :bar)           #=> TypeError: no implicit conversion of Symbol into Integer
[ GitHub ]

  
# File 'hash.c', line 4881

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 #eachEnumerator #each_pairEnumerator
Also known as: #each_pair

Calls the given block with each key-value pair, returning self:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.each_pair {|key, value| puts "#{key}: #{value}"}
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.equal?(h) # => true # Identity check

Output:

foo: 0
bar: 1
baz: 2

Returns an 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

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration)
h.each_pair {|key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3419

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_keyEnumerator

Calls the given block with each key; returns self:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.each_key {|key| puts key }
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.equal?(h) # => true # Identity check

Output:

foo
bar
baz

Returns an 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

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.each_key {|key| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3359

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 #eachEnumerator #each_pairEnumerator

Alias for #each.

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

Calls the given block with each value; returns self:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.each_value {|value| puts value }
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.equal?(h) # => true # Identity check

Output:

0
1
2

Returns an 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

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.each_value {|value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3312

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

#eql?(other) ⇒ Boolean

Returns true if hash and other are both hashes with the same content. The orders of each hashes are not compared.

[ GitHub ]

  
# File 'hash.c', line 4168

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

#fetch(key) ⇒ value #fetch(key, default) ⇒ value #fetch(key) {|key| ... } ⇒ value

Returns the value for the given #key.


When neither #default nor a block given:

  • If #key is found, returns its associated value.

  • Otherwise, raises an exception:

    h = {foo: 0, bar: 1, baz: 2}
    h.fetch(:bar) # => 1
    # Raises KeyError (key not found: :nosuch):
    h.fetch(:nosuch)

When #default is given, but no block:

  • If #key is found, returns its associated value.

  • Otherwise, returns the given #default:

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

When a block is given, but no #default:

  • If #key is found, returns its associated value.

  • Otherwise, calls the block with #key, and returns the block's return value.

    h = {foo: 0, bar: 1, baz: 2}
    h.fetch(:bar) { |key| fail 'Ignored'} # => 1
    h.fetch(:nosuch) { |key| "Value for #{key}"} # => "Value for nosuch"

When both #default and a block are given:

  • Ignores #default and issues a warning: 'block supersedes default value argument'.

  • If #key is found, returns its associated value.

  • Otherwise, calls the block with #key, and returns the block's return value.

    h = {foo: 0, bar: 1, baz: 2}
    h.fetch(:bar, :default) { |key| fail 'Ignored'} # => 1
    h.fetch(:nosuch, :default) { |key| "Value for #{key}"} # => "Value for nosuch"

Raises an exception if #key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):

h.fetch(BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 2250

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

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:

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

When a block 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"]

Raises an exception if any given key is not found:

h = {foo: 0, bar: 1, baz: 2}
h.fetch_values(:baz, :nosuch) # Raises KeyError (key not found: :nosuch)

Raises an exception if any given key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.fetch_values(:baz, BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 2890

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| ... } ⇒ Hash #selectEnumerator #filter {|key, value| ... } ⇒ Hash #filterEnumerator
Also known as: #select

filter is an alias for #select.

Returns a new Hash object whose entries are those for which the block returns a truthy value:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.select {|key, value| value < 2 }
h1 # => {:foo=>0, :bar=>1}
h1.equal?(h) # => false

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>
h1 = e.each {|key, value| value < 2 }
h1 # => {:foo=>0, :bar=>1}
h1.equal?(h) # => false

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.select {|key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 2941

static VALUE
rb_hash_select(VALUE hash)
{
    VALUE result;

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

#select! {|key, value| ... } ⇒ self? #select!Enumerator #filter! {|key, value| ... } ⇒ self? #filter!Enumerator
Also known as: #select!

filter! is an alias for #select!.

Returns self, whose entries are those for which the block returns a truthy value:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.select! {|key, value| value < 2 }
h # => {:foo=>0, :bar=>1}
h1.equal?(h) # => true

Returns nil if no entries were removed:

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

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!>
h1 = e.each { |key, value| value < 2 }
h1 # => {:foo=>0, :bar=>1}
h1.equal?(h) # => true

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration)
h.select! {|key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 2998

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

#flattenArray #flatten(level) ⇒ Array

Returns a new array that is a one-dimensional flattening of this hash. That is, for every key or value that is an array, extract its elements into the new array. Unlike Array#flatten, this method does not flatten recursively by default. The optional level argument determines the level of recursion to flatten.

a =  {1=> "one", 2 => [2,"two"], 3 => "three"}
a.flatten    # => [1, "one", 2, [2, "two"], 3, "three"]
a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
[ GitHub ]

  
# File 'hash.c', line 4611

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

Alias for #key?.

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

Alias for #value?.

#hashInteger

Compute a hash-code for this hash. Two hashes with the same content will have the same hash code (and will compare using #eql?).

See also Object#hash.

[ GitHub ]

  
# File 'hash.c', line 4196

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

Alias for #key?.

#index(value)

This method is for internal use only.
[ GitHub ]

  
# File 'hash.c', line 2452

static VALUE
rb_hash_index(VALUE hash, VALUE value)
{
    rb_warn_deprecated("Hash#index", "Hash#key");
    return rb_hash_key(hash, value);
}

#replace(other_hash) ⇒ self #initialize_copy(other_hash) ⇒ self

Alias for #replace.

#to_sString #inspectString

Alias for #to_s.

#invertHash

Returns a new hash created by using hsh's values as keys, and the keys as values. If a key with the same value already exists in the hsh, then the last one defined will be used, the earlier value(s) will be discarded.

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

If there is no key with the same value, invert is involutive.

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

The condition, no key with the same value, can be tested by comparing the size of inverted hash.

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

# two (or more) keys has the same value
h = { a: 1, b: 3, c: 1 }
h.size == h.invert.size #=> false
[ GitHub ]

  
# File 'hash.c', line 4246

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_ifEnumerator

Calls the block for each key-value pair; retains the entry if the block returns a truthy value; deletes the entry otherwise; returns self.

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

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>
h1 = e.each { |key, value| key.start_with?('b') }
h1 # => {:bar=>1, :baz=>2}
h1.object_id == h.object_id # => true

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.keep_if { |key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3038

static VALUE
rb_hash_keep_if(VALUE hash)
{
    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    rb_hash_modify_check(hash);
    if (!RHASH_TABLE_EMPTY_P(hash)) {
        rb_hash_foreach(hash, keep_if_i, hash);
    }
    return hash;
}

#key(value) ⇒ key?

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 so such value is found:

h.key(:nosuch) # => nil
[ GitHub ]

  
# File 'hash.c', line 2438

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
Also known as: #include?, #member?, #has_key?

Methods #has_key?, #key?, and #member? are aliases for #include?.

Returns true if #key is a key in self, otherwise false:

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

Raises an exception if #key is invalid (see Invalid Hash Keys):

# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.include?(BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 4004

MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
    if (hash_stlike_lookup(hash, key, NULL)) {
        return Qtrue;
    }
    else {
        return Qfalse;
    }
}

#keysArray

Returns a new Array containing all keys in self:

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

  
# File 'hash.c', line 3905

MJIT_FUNC_EXPORTED VALUE
rb_hash_keys(VALUE hash)
{
    st_index_t size = RHASH_SIZE(hash);
    VALUE keys =  rb_ary_new_capa(size);

    if (size == 0) return keys;

    if (ST_DATA_COMPATIBLE_P(VALUE)) {
        RARRAY_PTR_USE_TRANSIENT(keys, ptr, {
            if (RHASH_AR_TABLE_P(hash)) {
                size = ar_keys(hash, ptr, size);
            }
            else {
                st_table *table = RHASH_ST_TABLE(hash);
                size = st_keys(table, ptr, size);
            }
        });
        rb_gc_writebarrier_remember(keys);
	rb_ary_set_len(keys, size);
    }
    else {
	rb_hash_foreach(hash, keys_i, keys);
    }

    return keys;
}

#lengthInteger #sizeInteger
Also known as: #size

Returns the count of entries in self:

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

length is an alias for #size.

[ GitHub ]

  
# File 'hash.c', line 3245

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

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

Alias for #key?.

#merge(other_hash1, other_hash2, ...) ⇒ Hash #merge(other_hash1, other_hash2, ...) {|key, oldval, newval| ... } #-

Returns a new hash that combines the contents of the receiver and the contents of the given hashes.

If no block is given, entries with duplicate keys are overwritten with the values from each other_hash successively, otherwise the value for each duplicate key is determined by calling the block with the key, its value in the receiver and its value in each other_hash.

When called without any argument, returns a copy of the receiver.

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 246, "c" => 300 }
h3 = { "b" => 357, "d" => 400 }
h1.merge          #=> {"a"=>100, "b"=>200}
h1.merge(h2)      #=> {"a"=>100, "b"=>246, "c"=>300}
h1.merge(h2, h3)  #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
h1.merge(h2) {|key, oldval, newval| newval - oldval}
                  #=> {"a"=>100, "b"=>46,  "c"=>300}
h1.merge(h2, h3) {|key, oldval, newval| newval - oldval}
                  #=> {"a"=>100, "b"=>311, "c"=>300, "d"=>400}
h1                #=> {"a"=>100, "b"=>200}
[ GitHub ]

  
# File 'hash.c', line 4452

static VALUE
rb_hash_merge(int argc, VALUE *argv, VALUE self)
{
    return rb_hash_update(argc, argv, rb_hash_dup(self));
}

#merge!(other_hash1, other_hash2, ...) ⇒ Hash #update(other_hash1, other_hash2, ...) ⇒ Hash #merge!(other_hash1, other_hash2, ...) {|key, oldval, newval| ... } #- #update(other_hash1, other_hash2, ...) {|key, oldval, newval| ... } #-
Also known as: #update

Adds the contents of the given hashes to the receiver.

If no block is given, entries with duplicate keys are overwritten with the values from each other_hash successively, otherwise the value for each duplicate key is determined by calling the block with the key, its value in the receiver and its value in each other_hash.

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

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

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

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

#update is an alias for merge!.

[ GitHub ]

  
# File 'hash.c', line 4348

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

Searches through the hash comparing obj with the value using #==. Returns the first key-value pair (two-element array) that matches. See also Array#rassoc.

a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
a.rassoc("two")    #=> [2, "two"]
a.rassoc("four")   #=> nil
[ GitHub ]

  
# File 'hash.c', line 4572

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 will have become invalid if the hash value of a key has changed since the entry was created. See Modifying an Active Hash Key.


Raises an exception if called while an iterator is traversing the hash:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (rehash during iteration):
h.each { |x| h.rehash }
[ GitHub ]

  
# File 'hash.c', line 2081

VALUE
rb_hash_rehash(VALUE hash)
{
    VALUE tmp;
    st_table *tbl;

    if (RHASH_ITER_LEV(hash) > 0) {
	rb_raise(rb_eRuntimeError, "rehash during iteration");
    }
    rb_hash_modify_check(hash);
    if (RHASH_AR_TABLE_P(hash)) {
        tmp = hash_alloc(0);
        ar_alloc_table(tmp);
        rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
        ar_free_and_clear_table(hash);
        ar_copy(hash, tmp);
        ar_free_and_clear_table(tmp);
    }
    else if (RHASH_ST_TABLE_P(hash)) {
        st_table *old_tab = RHASH_ST_TABLE(hash);
        tmp = hash_alloc(0);
        tbl = st_init_table_with_size(old_tab->type, old_tab->num_entries);
        RHASH_ST_TABLE_SET(tmp, tbl);
        rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
        st_free_table(old_tab);
        RHASH_ST_TABLE_SET(hash, tbl);
        RHASH_ST_CLEAR(tmp);
    }
    hash_verify(hash);
    return hash;
}

#reject {|key, value| ... } ⇒ Hash #rejectEnumerator

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}
[ GitHub ]

  
# File 'hash.c', line 2766

VALUE
rb_hash_reject(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    if (RTEST(ruby_verbose)) {
	VALUE klass;
	if (HAS_EXTRA_STATES(hash, klass)) {
	    rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash);
	}
    }
    result = rb_hash_new();
    if (!RHASH_EMPTY_P(hash)) {
	rb_hash_foreach(hash, reject_i, result);
    }
    return result;
}

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

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

h = {foo: 0, bar: 1, baz: 2}
h1 = h.reject! {|key, value| value < 2 }
h1 # => {:baz=>2}
h1.equal?(h) # => true # Identity check

Returns nil if no entries are removed:

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

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}
h1.equal?(h) # => true # Identity check

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.reject! { |key, value| h[:new_Key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 2725

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 Also known as: #initialize_copy

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

h = {foo: 0, bar: 1, baz: 2}
h1 = h.replace({bat: 3, bam: 4})
h1 # => {:bat=>3, :bam=>4}
h1.equal?(h) # => true # Identity check

Raises an exception if other_hash is not a Hash-convertible object:

h = {}
# Raises TypeError (no implicit conversion of Symbol into Hash):
h.replace(:not_a_hash)
[ GitHub ]

  
# File 'hash.c', line 3195

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

    COPY_DEFAULT(hash, hash2);

    if (RHASH_AR_TABLE_P(hash)) {
        if (RHASH_AR_TABLE_P(hash2)) {
            ar_clear(hash);
        }
        else {
            ar_free_and_clear_table(hash);
            RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), RHASH_SIZE(hash2)));
        }
    }
    else {
        if (RHASH_AR_TABLE_P(hash2)) {
            st_free_table(RHASH_ST_TABLE(hash));
            RHASH_ST_CLEAR(hash);
        }
        else {
            st_clear(RHASH_ST_TABLE(hash));
            RHASH_TBL_RAW(hash)->type = RHASH_ST_TABLE(hash2)->type;
        }
    }
    rb_hash_foreach(hash2, rb_hash_rehash_i, (VALUE)hash);

    rb_gc_writebarrier_remember(hash);

    return hash;
}

#select {|key, value| ... } ⇒ Hash #selectEnumerator #filter {|key, value| ... } ⇒ Hash #filterEnumerator

Alias for #filter.

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

Alias for #filter!.

#shiftArray, value

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 the default value if the hash is empty (see Default Values):

h = {}
h.shift # => nil
[ GitHub ]

  
# File 'hash.c', line 2600

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 (RHASH_ITER_LEV(hash) == 0) {
            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 (var.key != Qundef) {
                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 (RHASH_ITER_LEV(hash) == 0) {
            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 (var.key != Qundef) {
		rb_hash_delete_entry(hash, var.key);
		return rb_assoc_new(var.key, var.val);
	    }
	}
    }
    return rb_hash_default_value(hash, Qnil);
}

#lengthInteger #sizeInteger

Alias for #length.

#slice(*keys) ⇒ Hash

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

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

Raises an exception if any given key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.slice(:foo, BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 2804

static VALUE
rb_hash_slice(int argc, VALUE *argv, VALUE hash)
{
    int i;
    VALUE key, value, result;

    if (argc == 0 || RHASH_EMPTY_P(hash)) {
	return rb_hash_new();
    }
    result = rb_hash_new_with_size(argc);

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

    return result;
}

#[]=(key, value) ⇒ value #store(key, value)

Alias for #[]=.

#to_aArray

Returns a new Array of 2-element Array objects; each nested Array contains the key and value for a hash entry:

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

  
# File 'hash.c', line 3711

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

For an instance of Hash, returns self:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.to_h
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.equal?(h) #  => true # Identity check

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

class MyHash < Hash; end
h = MyHash[foo: 0, bar: 1, baz: 2]
h # => {:foo=>0, :bar=>1, :baz=>2}
h.class # => MyHash
h1 = h.to_h
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.class # => Hash

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}

Raises an exception if the block does not return an Array:

h = {foo: 0, bar: 1, baz: 2}
# Raises TypeError (wrong element type Symbol (expected array)):
h1 = h.to_h {|key, value| :array }

Raises an exception if the block returns an Array of size different from 2:

h = {foo: 0, bar: 1, baz: 2}
# Raises ArgumentError (element has wrong array length (expected 2, was 3)):
h1 = h.to_h {|key, value| [0, 1, 2] }

Raises an exception if the block returns an invalid key (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>)
 h1 = h.to_h {|key, value| [BasicObject.new, 0] }

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration):
h.to_h {|key, value| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3876

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:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.to_hash
h1 # => {:foo=>0, :bar=>1, :baz=>2}
h1.equal?(h) # => true # Identity check
[ GitHub ]

  
# File 'hash.c', line 3784

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

#to_procProc

Returns a ::Proc which maps keys to values.

h = {a:1, b:2}
hp = h.to_proc
hp.call(:a)          #=> 1
hp.call(:b)          #=> 2
hp.call(:c)          #=> nil
[:a, :b, :c].map(&h) #=> [1, 2, nil]
[ GitHub ]

  
# File 'hash.c', line 5015

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

#to_sString Also known as: #inspect

Returns a new String containing the hash entries:

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

to_s is an alias for #inspect.

[ GitHub ]

  
# File 'hash.c', line 3766

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

#transform_keys {|key| ... } ⇒ Hash #transform_keysEnumerator

Returns a new Hash object; each entry has:

  • A key provided by the block.

  • The value from self.

Transform keys:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_keys {|key| key.to_s }
h1 # => {"foo"=>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}

Raises an exception if the block returns an invalid key (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>)
h.transform_keys {|key| BasicObject.new }

Raises an exception if the block attempts to add a new key:

h = {foo: 0, bar: 1, baz: 2}
# Raises RuntimeError (can't add a new key into hash during iteration)
h.transform_keys {|key| h[:new_key] = 3 }
[ GitHub ]

  
# File 'hash.c', line 3498

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!Enumerator

Returns self with new keys provided by the block:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_keys! {|key| key.to_s }
h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}
h1.equal?(h) # => true # Identity check

Overwrites values for duplicate keys:

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

Allows the block to add a new entry:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_keys! {|key| h[:new_key] = key.to_s }
h1 # => {:new_key=>"baz", "foo"=>0, "bar"=>1, "baz"=>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}

Raises an exception if the block returns an invalid key (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>)
h.transform_keys! {|key| BasicObject.new }
[ GitHub ]

  
# File 'hash.c', line 3563

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 pairs = rb_hash_flatten(0, NULL, hash);
        rb_hash_clear(hash);
        for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
            VALUE key = RARRAY_AREF(pairs, i), new_key, val;

            if (!trans) {
                new_key = rb_yield(key);
            }
            else if ((new_key = rb_hash_lookup2(trans, key, Qundef)) != Qundef) {
                /* use the transformed key */
            }
            else if (block_given) {
                new_key = rb_yield(key);
            }
            else {
                new_key = key;
            }
            val = RARRAY_AREF(pairs, i+1);
            rb_hash_aset(hash, new_key, val);
        }
    }
    return hash;
}

#transform_values {|value| ... } ⇒ Hash #transform_valuesEnumerator

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}

Ignores an attempt in the block to add a new key:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_values {|value| h[:new_key] = 3; 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}
[ GitHub ]

  
# File 'hash.c', line 3644

static VALUE
rb_hash_transform_values(VALUE hash)
{
    VALUE result;

    RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
    result = hash_copy(hash_alloc(rb_cHash), hash);

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

    return result;
}

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

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

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_values! {|value| value * 100}
h1 # => {:foo=>0, :bar=>100, :baz=>200}
h1.equal?(h) # => true # Identity check

Allows the block to add a new entry:

h = {foo: 0, bar: 1, baz: 2}
h1 = h.transform_values! {|value| h[:new_key] = 3; value * 100 }
h1 # => {:foo=>0, :bar=>100, :baz=>200, :new_key=>3}

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}
[ GitHub ]

  
# File 'hash.c', line 3681

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!(other_hash1, other_hash2, ...) ⇒ Hash #update(other_hash1, other_hash2, ...) ⇒ Hash #merge!(other_hash1, other_hash2, ...) {|key, oldval, newval| ... } #- #update(other_hash1, other_hash2, ...) {|key, oldval, newval| ... } #-

Alias for #merge!.

#value?(value) ⇒ Boolean Also known as: #has_value?

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

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

  
# File 'hash.c', line 4037

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

#valuesArray

Returns a new Array containing all values in self:

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

  
# File 'hash.c', line 3949

VALUE
rb_hash_values(VALUE hash)
{
    VALUE values;
    st_index_t size = RHASH_SIZE(hash);

    values = rb_ary_new_capa(size);
    if (size == 0) return values;

    if (ST_DATA_COMPATIBLE_P(VALUE)) {
        if (RHASH_AR_TABLE_P(hash)) {
            rb_gc_writebarrier_remember(values);
            RARRAY_PTR_USE_TRANSIENT(values, ptr, {
                size = ar_values(hash, ptr, size);
            });
        }
        else if (RHASH_ST_TABLE_P(hash)) {
            st_table *table = RHASH_ST_TABLE(hash);
            rb_gc_writebarrier_remember(values);
            RARRAY_PTR_USE_TRANSIENT(values, ptr, {
                size = st_values(table, ptr, size);
            });
        }
	rb_ary_set_len(values, size);
    }

    else {
	rb_hash_foreach(hash, values_i, values);
    }

    return values;
}

#values_at(*keys) ⇒ Array

Returns a new Array containing values for the given #keys:

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

Returns an empty ::Array if no arguments given:

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

Raises an exception if any given key is invalid (see Invalid Hash Keys):

h = {foo: 0, bar: 1, baz: 2}
# Raises NoMethodError (undefined method `hash' for #<BasicObject>):
h.values_at(BasicObject.new)
[ GitHub ]

  
# File 'hash.c', line 2846

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