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,
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 {Kernel.html#method-i-Hash }.

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.

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

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

What’s Here

First, what’s elsewhere. Class Hash:

  • Inherits from class Object.

  • Includes module Enumerable, which provides dozens of additional methods.

Here, class Hash provides methods that are useful for:

  • {#class-Hash-label-Methods+for+Creating+a+Hash Creating a }

  • Setting State

  • Querying

  • Comparing

  • Fetching

  • Assigning

  • Deleting

  • Iterating

  • Converting

  • Transforming Keys and Values

  • And more.…

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 proper 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 givan 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

Instance Attribute Summary

Instance Method Summary

::Enumerable - Included

#all?

Returns whether every element meets a given criterion.

#any?

Returns whether any element meets a given criterion.

#chain

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

#chunk

Each element in the returned enumerator is a 2-element array consisting of:

#chunk_while

Creates an enumerator for each chunked elements.

#collect

Alias for Enumerable#map.

#collect_concat
#compact

Returns an array of all non-nil elements:

#count

Returns the count of elements, based on an argument or block criterion, if given.

#cycle

When called with positive integer argument n and a block, calls the block with each element, then does so again, until it has done so n times; returns nil:

#detect

Alias for Enumerable#find.

#drop

For positive integer n, returns an array containing all but the first n elements:

#drop_while

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point:

#each_cons

Calls the block with each successive overlapped n-tuple of elements; returns self:

#each_entry

Calls the given block with each element, converting multiple values from yield to an array; returns self:

#each_slice

Calls the block with each successive disjoint n-tuple of elements; returns self:

#each_with_index

With a block given, calls the block with each element and its index; returns self:

#each_with_object

Calls the block once for each element, passing both the element and the given object:

#entries

Alias for Enumerable#to_a.

#filter

Returns an array containing elements selected by the block.

#filter_map

Returns an array containing truthy elements returned by the block.

#find

Returns the first element for which the block returns a truthy value.

#find_all
#find_index

Returns the index of the first element that meets a specified criterion, or nil if no such element is found.

#first

Returns the first element or elements.

#flat_map

Returns an array of flattened objects returned by the block.

#grep

Returns an array of objects based elements of self that match the given pattern.

#grep_v

Returns an array of objects based on elements of self that don’t match the given pattern.

#group_by

With a block given returns a hash:

#include?
#inject

Returns an object formed from operands via either:

#lazy

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

#map

Returns an array of objects returned by the block.

#max

Returns the element with the maximum element according to a given criterion.

#max_by

Returns the elements for which the block returns the maximum values.

#member?

Returns whether for any element object == element:

#min

Returns the element with the minimum element according to a given criterion.

#min_by

Returns the elements for which the block returns the minimum values.

#minmax

Returns a 2-element array containing the minimum and maximum elements according to a given criterion.

#minmax_by

Returns a 2-element array containing the elements for which the block returns minimum and maximum values:

#none?

Returns whether no element meets a given criterion.

#one?

Returns whether exactly one element meets a given criterion.

#partition

With a block given, returns an array of two arrays:

#reduce
#reject

Returns an array of objects rejected by the block.

#reverse_each

With a block given, calls the block with each element, but in reverse order; returns self:

#select
#slice_after

Creates an enumerator for each chunked elements.

#slice_before

With argument pattern, returns an enumerator that uses the pattern to partition elements into arrays (“slices”).

#slice_when

Creates an enumerator for each chunked elements.

#sort

Returns an array containing the sorted elements of self.

#sort_by

With a block given, returns an array of elements of self, sorted according to the value returned by the block for each element.

#sum

With no block given, returns the sum of initial_value and the elements:

#take

For non-negative integer n, returns the first n elements:

#take_while

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements up to that point:

#tally

Returns a hash containing the counts of equal elements:

#to_a

Returns an array containing the items in self:

#to_h

When self consists of 2-element arrays, returns a hash each of whose entries is the key-value pair formed from one of those arrays:

#uniq

With no block, returns a new array containing only unique elements; the array has no two elements e0 and e1 such that e0.eql?(e1):

#zip

With no block given, returns a new array new_array of size self.size whose elements are arrays.

Constructor Details

.new(default_value = nil) ⇒ 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 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"
[ GitHub ]

  
# File 'hash.c', line 1811

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 .[](hash) ⇒ Hash .[]([*2_element_arrays] ) ⇒ Hash .[](*objects) ⇒ Hash

Returns a new Hash object populated with the given objects, if any. See .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.

[ GitHub ]

  
# File 'hash.c', line 1866

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 1986

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 1964

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.

[ GitHub ]

  
# File 'hash.c', line 1943

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

Instance Attribute Details

#compare_by_identityself (readonly)

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

  
# File 'hash.c', line 4411

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

    return hash;
}

#compare_by_identity?Boolean (readonly)

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

[ GitHub ]

  
# File 'hash.c', line 4441

MJIT_FUNC_EXPORTED VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
    return RBOOL(RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash);
}

#default_procProc? (rw)

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

  
# File 'hash.c', line 2274

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

  
# File 'hash.c', line 2297

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 3030

static VALUE
rb_hash_empty_p(VALUE hash)
{
    return RBOOL(RHASH_EMPTY_P(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
[ GitHub ]

  
# File 'hash.c', line 4655

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

  
# File 'hash.c', line 4636

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

  
# File 'hash.c', line 3807

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

  
# File 'hash.c', line 4693

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

  
# File 'hash.c', line 4674

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 2110

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

#store is an alias for []=.

Associates the given value with the given #key; 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}
[ GitHub ]

  
# File 'hash.c', line 2937

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?Boolean #any?(object) ⇒ Boolean #any? {|key, value| ... } ⇒ Boolean

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

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

  
# File 'hash.c', line 4537

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

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.

[ GitHub ]

  
# File 'hash.c', line 4170

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

[ GitHub ]

  
# File 'hash.c', line 2862

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

    return hash;
}

#compactHash

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

  
# File 'hash.c', line 4346

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

[ GitHub ]

  
# File 'hash.c', line 4367

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 4726

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

  
# File 'hash.c', line 2227

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.

[ GitHub ]

  
# File 'hash.c', line 2254

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

  
# File 'hash.c', line 2430

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

  
# File 'hash.c', line 2554

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

  
# File 'hash.c', line 4595

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

each is an alias for #each_pair.

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

  
# File 'hash.c', line 3158

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

  
# File 'hash.c', line 3105

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

  
# File 'hash.c', line 3067

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

  
# File 'hash.c', line 3832

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.

[ GitHub ]

  
# File 'hash.c', line 2673

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.

[ GitHub ]

  
# File 'hash.c', line 2165

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.

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.

[ GitHub ]

  
# File 'hash.c', line 2735

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

  
# File 'hash.c', line 2774

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

  
# File 'hash.c', line 2807

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

  
# File 'hash.c', line 4285

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

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

Alias for #value?.

#hashInteger

Returns the Integer hash-code for the hash.

Two Hash objects have the same hash-code if their content is the same (regardless or order):

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

  
# File 'hash.c', line 3864

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

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

Alias for #replace.

#to_sString #inspectString

Alias for #to_s.

#invertHash

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

  
# File 'hash.c', line 3899

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

  
# File 'hash.c', line 2838

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.

[ GitHub ]

  
# File 'hash.c', line 2343

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.

[ GitHub ]

  
# File 'hash.c', line 3668

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

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

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:

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

length is an alias for #size.

[ GitHub ]

  
# File 'hash.c', line 3009

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

#mergecopy_of_self #merge(*other_hashes) ⇒ Hash #merge(*other_hashes) {|key, old_value, new_value| ... } ⇒ Hash

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

  
# File 'hash.c', line 4114

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

Merges each of other_hashes into self; returns self.

Each argument in other_hashes must be a Hash.

Method #update is an alias for #merge!.

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

  
# File 'hash.c', line 3995

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

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.

[ GitHub ]

  
# File 'hash.c', line 4231

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.

[ GitHub ]

  
# File 'hash.c', line 2024

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 2616

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

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

  
# File 'hash.c', line 2584

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 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}
h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4}
[ GitHub ]

  
# File 'hash.c', line 2968

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)) {
        ar_free_and_clear_table(hash);
    }
    else {
        st_free_table(RHASH_ST_TABLE(hash));
        RHASH_ST_CLEAR(hash);
    }
    hash_copy(hash, hash2);
    if (RHASH_EMPTY_P(hash2) && RHASH_ST_TABLE_P(hash2)) {
        /* ident hash */
        RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), 0));
    }

    rb_gc_writebarrier_remember(hash);

    return hash;
}

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

Alias for #filter.

#select! {|key, value| ... } ⇒ self? #select!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).

[ GitHub ]

  
# File 'hash.c', line 2482

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}
h.slice(:baz, :foo) # => {:baz=>2, :foo=>0}

Any given #keys that are not found are ignored.

[ GitHub ]

  
# File 'hash.c', line 2641

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 (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 a key-value pair from self:

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

  
# File 'hash.c', line 3423

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.

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

  
# File 'hash.c', line 3550

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.

[ GitHub ]

  
# File 'hash.c', line 3492

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

  
# File 'hash.c', line 4720

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

#to_sString Also known as: #inspect

Returns a new String containing the hash entries:

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

to_s is an alias for #inspect.

[ GitHub ]

  
# File 'hash.c', line 3478

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_keys(hash2) ⇒ Hash #transform_keys(hash2) {|other_key| ... } ⇒ Hash #transform_keysEnumerator

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

  
# File 'hash.c', line 3236

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

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

[ GitHub ]

  
# File 'hash.c', line 3276

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_tmp_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 ((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);
            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| ... } ⇒ 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}

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 3361

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

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

  
# File 'hash.c', line 3393

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

Alias for #merge!.

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

::Method #value? is an alias for #has_value?.

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

[ GitHub ]

  
# File 'hash.c', line 3696

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 3623

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(:baz, :foo) # => [2, 0]

The default values are returned for any keys that are not found:

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

  
# File 'hash.c', line 2703

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