Class: Hash
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
Hash.new
-
Method
Hash[]
-
Literal form:
{}
.
You can create a Hash by calling method Hash.new.
Create an empty Hash:
h = Hash.new
h # => {}
h.class # => Hash
You can create a Hash by calling method Hash.[].
Create an empty Hash:
h = Hash[]
h # => {}
Create a Hash with initial entries:
h = Hash[foo: 0, bar: 1, baz: 2]
h # => {:foo=>0, :bar=>1, :baz=>2}
You can create a Hash by using its literal form (curly braces).
Create an empty Hash:
h = {}
h # => {}
Create a Hash with initial entries:
h = {foo: 0, bar: 1, baz: 2}
h # => {:foo=>0, :bar=>1, :baz=>2}
Hash Value Basics
The simplest way to retrieve a Hash value (instance method #[]):
h = {foo: 0, bar: 1, baz: 2}
h[:foo] # => 0
The simplest way to create or update a Hash value (instance method #[]=):
h = {foo: 0, bar: 1, baz: 2}
h[:bat] = 3 # => 3
h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
h[:foo] = 4 # => 4
h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3}
The simplest way to delete a Hash entry (instance method #delete):
h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {:foo=>0, :baz=>2}
Entry Order
A Hash object presents its entries in the order of their creation. This is seen in:
-
Iterative methods such as
each
,each_key
,each_pair
,each_value
. -
Other order-sensitive methods such as
shift
,keys
,values
. -
The String returned by method
inspect
.
A new Hash has its initial ordering per the given entries:
h = Hash[foo: 0, bar: 1]
h # => {:foo=>0, :bar=>1}
New entries are added at the end:
h[:baz] = 2
h # => {:foo=>0, :bar=>1, :baz=>2}
Updating a value does not affect the order:
h[:baz] = 3
h # => {:foo=>0, :bar=>1, :baz=>3}
But re-creating a deleted entry can affect the order:
h.delete(:foo)
h[:foo] = 5
h # => {:bar=>1, :baz=>3, :foo=>5}
Hash Keys
Hash Key Equivalence
Two objects are treated as the same hash key when their hash
value is identical and the two objects are eql?
to each other.
Modifying an Active Hash Key
Modifying a Hash key while it is in use damages the hash’s index.
This Hash has keys that are Arrays:
a0 = [ :foo, :bar ]
a1 = [ :baz, :bat ]
h = {a0 => 0, a1 => 1}
h.include?(a0) # => true
h[a0] # => 0
a0.hash # => 110002110
Modifying array element a0[0]
changes its hash value:
a0[0] = :bam
a0.hash # => 1069447059
And damages the Hash index:
h.include?(a0) # => false
h[a0] # => nil
You can repair the hash index using method rehash
:
h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
h.include?(a0) # => true
h[a0] # => 0
A String key is always safe. That’s because an unfrozen String passed as a key will be replaced by a duplicated and frozen String:
s = 'foo'
s.frozen? # => false
h = {s => 0}
first_key = h.keys.first
first_key.frozen? # => true
User-Defined Hash Keys
To be useable as a Hash key, objects must implement the methods hash
and eql?
. Note: this requirement does not apply if the Hash uses #compare_by_id 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(, title)
@author =
@title = title
end
def ==(other)
self.class === other &&
other. == @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 Hash.new or with method #default=
h = Hash.new(-1)
h.default # => -1
h.default = 0
h.default # => 0
This default value is returned for #[], #values_at and #dig when a key is not found:
counts = {foo: 42}
counts.default # => nil (default)
counts[:foo] = 42
counts[:bar] # => nil
counts.default = 0
counts[:bar] # => 0
counts.values_at(:foo, :bar, :baz) # => [42, 0, 0]
counts.dig(:bar) # => 0
Note that the default value is used without being duplicated. It is not advised to set the default value to a mutable object:
synonyms = Hash.new([])
synonyms[:hello] # => []
synonyms[:hello] << :hi # => [:hi], but this mutates the default!
synonyms.default # => [:hi]
synonyms[:world] << :universe
synonyms[:world] # => [:hi, :universe], oops
synonyms.keys # => [], oops
To use a mutable object as default, it is recommended to use a default proc
Default Proc
When the default proc for a Hash is set (i.e., not nil
), the default value returned by method #[] is determined by the default proc alone.
You can retrieve the default proc with method #default_proc:
h = Hash.new
h.default_proc # => nil
You can set the default proc by calling Hash.new with a block or calling the method #default_proc=
h = Hash.new { |hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
h.default_proc = proc { |hash, key| "Default value for #{key.inspect}" }
h.default_proc.class # => Proc
When the default proc is set (i.e., not nil
) and method #[] is called with with a non-existent key, #[] calls the default proc with both the Hash object itself and the missing key, then returns the proc’s return value:
h = Hash.new { |hash, key| "Default value for #{key}" }
h[:nosuch] # => "Default value for nosuch"
Note that in the example above no entry for key :nosuch
is created:
h.include?(:nosuch) # => false
However, the proc itself can add a new entry:
synonyms = Hash.new { |hash, key| hash[key] = [] }
synonyms.include?(:hello) # => false
synonyms[:hello] << :hi # => [:hi]
synonyms[:world] << :universe # => [:universe]
synonyms.keys # => [:hello, :world]
Note that setting the default proc will clear the default value and vice versa.
Class Method Summary collapse
-
.[](*args) ⇒ Object
Returns a new Hash object populated with the given objects, if any.
-
.ruby2_keywords_hash(hash) ⇒ Hash
Duplicates a given hash and adds a ruby2_keywords flag.
-
.ruby2_keywords_hash?(hash) ⇒ Boolean
Checks if a given hash is flagged by Module#ruby2_keywords (or Proc#ruby2_keywords).
-
.try_convert(obj) ⇒ Object?
If
obj
is a Hash object, returnsobj
.
Instance Method Summary collapse
-
#<(other_hash) ⇒ Boolean
Returns
true
ifhash
is a proper subset ofother_hash
,false
otherwise: h1 = 0, bar: 1 h2 = 0, bar: 1, baz: 2 h1 < h2 # => true h2 < h1 # => false h1 < h1 # => false. -
#<=(other_hash) ⇒ Boolean
Returns
true
ifhash
is a subset ofother_hash
,false
otherwise: h1 = 0, bar: 1 h2 = 0, bar: 1, baz: 2 h1 <= h2 # => true h2 <= h1 # => false h1 <= h1 # => true. -
#==(object) ⇒ Boolean
Returns
true
if all of the following are true: *object
is a Hash object. -
#>(other_hash) ⇒ Boolean
Returns
true
ifhash
is a proper superset ofother_hash
,false
otherwise: h1 = 0, bar: 1, baz: 2 h2 = 0, bar: 1 h1 > h2 # => true h2 > h1 # => false h1 > h1 # => false. -
#>=(other_hash) ⇒ Boolean
Returns
true
ifhash
is a superset ofother_hash
,false
otherwise: h1 = 0, bar: 1, baz: 2 h2 = 0, bar: 1 h1 >= h2 # => true h2 >= h1 # => false h1 >= h1 # => true. -
#[](key) ⇒ Object
Returns the value associated with the given
key
, if found: h = 0, bar: 1, baz: 2 h # => 0. - #[]= ⇒ Object
-
#any?(*args) ⇒ Object
Returns
true
if any element satisfies a given criterion;false
otherwise. -
#assoc(key) ⇒ nil
If the given
key
is found, returns a 2-element Array containing that key and its value: h = 0, bar: 1, baz: 2 h.assoc(:bar) # => [:bar, 1]. -
#clear ⇒ self
Removes all hash entries; returns
self
. -
#compact ⇒ Object
Returns a copy of
self
with allnil
-valued entries removed: h = 0, bar: nil, baz: 2, bat: nil h1 = h.compact h1 # => :baz=>2. -
#compact! ⇒ self?
Returns
self
with all itsnil
-valued entries removed (in place): h = 0, bar: nil, baz: 2, bat: nil h.compact! # => :baz=>2. -
#compare_by_identity ⇒ self
Sets
self
to consider only identity in comparing keys; two keys are considered the same only if they are the same object; returnsself
. -
#compare_by_identity? ⇒ Boolean
Returns
true
if #compare_by_identity has been called,false
otherwise. - #deconstruct_keys(keys) ⇒ Object
-
#default(*args) ⇒ Object
Returns the default value for the given
key
. -
#default=(value) ⇒ Object
Sets the default value to
value
; returnsvalue
: h = {} h.default # => nil h.default = false # => false h.default # => false. -
#default_proc ⇒ Proc?
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. -
#default_proc=(proc) ⇒ Proc
Sets the default proc for
self
toproc
: (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. -
#delete(key) ⇒ Object
Deletes the entry for the given
key
and returns its associated value. -
#delete_if ⇒ Object
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 = 0, bar: 1, baz: 2 h.delete_if {|key, value| value > 0 } # => :foo=>0. -
#dig(key, *identifiers) ⇒ Object
Finds and returns the object in nested objects that is specified by
key
andidentifiers
. -
#each ⇒ Object
Hash#each is an alias for Hash#each_pair.
-
#each_key ⇒ Object
Calls the given block with each key; returns
self
: h = 0, bar: 1, baz: 2 h.each_key {|key| puts key } # => :bar=>1, :baz=>2 Output: foo bar baz. -
#each_pair ⇒ Object
Hash#each is an alias for Hash#each_pair.
-
#each_value ⇒ Object
Calls the given block with each value; returns
self
: h = 0, bar: 1, baz: 2 h.each_value {|value| puts value } # => :bar=>1, :baz=>2 Output: 0 1 2. -
#empty? ⇒ Boolean
Returns
true
if there are no hash entries,false
otherwise: {}.empty? # => true 0, bar: 1, baz: 2.empty? # => false. -
#eql?(object) ⇒ Boolean
Returns
true
if all of the following are true: *object
is a Hash object. -
#except(*keys) ⇒ Hash
Returns a new Hash excluding entries for the given
keys
: h = { a: 100, b: 200, c: 300 } h.except(:a) #=> :c=>300. -
#fetch(*args) ⇒ Object
Returns the value for the given
key
, if found. -
#fetch_values(*args) ⇒ Object
Returns a new Array containing the values associated with the given keys *keys: h = 0, bar: 1, baz: 2 h.fetch_values(:baz, :foo) # => [2, 0].
-
#filter ⇒ Object
Hash#filter is an alias for Hash#select.
-
#filter! ⇒ Object
Hash#filter! is an alias for Hash#select!.
-
#flatten(*args) ⇒ Object
Returns a new Array object that is a 1-dimensional flattening of
self
. -
#has_key?(key) ⇒ Object
Methods #has_key?, #key?, and #member? are aliases for #include?.
-
#has_value?(value) ⇒ Boolean
Returns
true
ifvalue
is a value inself
, otherwisefalse
. -
#hash ⇒ Integer
Returns the Integer hash-code for the hash.
-
#include?(key) ⇒ Object
Methods #has_key?, #key?, and #member? are aliases for #include?.
-
#initialize(*args) ⇒ Object
constructor
Returns a new empty Hash object.
-
#replace(other_hash) ⇒ self
Replaces the entire contents of
self
with the contents ofother_hash
; returnsself
: h = 0, bar: 1, baz: 2 h.replace(3, bam: 4) # => :bam=>4. -
#inspect ⇒ Object
(also: #to_s)
Returns a new String containing the hash entries: h = 0, bar: 1, baz: 2 h.inspect # => “:bar=>1, :baz=>2”.
-
#invert ⇒ Object
Returns a new Hash object with the each key-value pair inverted: h = 0, bar: 1, baz: 2 h1 = h.invert h1 # => 1=>:bar, 2=>:baz.
-
#keep_if ⇒ Object
Calls the block for each key-value pair; retains the entry if the block returns a truthy value; otherwise deletes the entry; returns
self
. -
#key(value) ⇒ nil
Returns the key for the first-found entry with the given
value
(see Entry Order): h = 0, bar: 2, baz: 2 h.key(0) # => :foo h.key(2) # => :bar. -
#key?(key) ⇒ Object
Methods #has_key?, #key?, and #member? are aliases for #include?.
-
#keys ⇒ Object
Returns a new Array containing all keys in
self
: h = 0, bar: 1, baz: 2 h.keys # => [:foo, :bar, :baz]. -
#length ⇒ Object
Returns the count of entries in
self
: 0, bar: 1, baz: 2.length # => 3. -
#member?(key) ⇒ Object
Methods #has_key?, #key?, and #member? are aliases for #include?.
-
#merge(*args) ⇒ Object
Returns the new Hash formed by merging each of
other_hashes
into a copy ofself
. -
#merge!(*args) ⇒ Object
Merges each of
other_hashes
intoself
; returnsself
. -
#rassoc(value) ⇒ nil
Returns a new 2-element Array consisting of the key and value of the first-found entry whose value is
==
to value (see Entry Order): h = 0, bar: 1, baz: 1 h.rassoc(1) # => [:bar, 1]. -
#rehash ⇒ self
Rebuilds the hash table by recomputing the hash index for each key; returns
self
. -
#reject ⇒ Object
Returns a new Hash object whose entries are all those from
self
for which the block returnsfalse
ornil
: h = 0, bar: 1, baz: 2 h1 = h.reject {|key, value| key.start_with?(‘b’) } h1 # => :foo=>0. -
#reject! ⇒ Object
Returns
self
, whose remaining entries are those for which the block returnsfalse
ornil
: h = 0, bar: 1, baz: 2 h.reject! {|key, value| value < 2 } # => :baz=>2. -
#replace(other_hash) ⇒ self
Replaces the entire contents of
self
with the contents ofother_hash
; returnsself
: h = 0, bar: 1, baz: 2 h.replace(3, bam: 4) # => :bam=>4. -
#select ⇒ Object
Hash#filter is an alias for Hash#select.
-
#select! ⇒ Object
Hash#filter! is an alias for Hash#select!.
-
#shift ⇒ Array
Removes the first hash entry (see Entry Order); returns a 2-element Array containing the removed key and value: h = 0, bar: 1, baz: 2 h.shift # => [:foo, 0] h # => :baz=>2.
-
#size ⇒ Object
Returns the count of entries in
self
: 0, bar: 1, baz: 2.length # => 3. -
#slice(*keys) ⇒ Object
Returns a new Hash object containing the entries for the given
keys
: h = 0, bar: 1, baz: 2 h.slice(:baz, :foo) # => :foo=>0. - #store ⇒ Object
-
#to_a ⇒ Object
Returns a new Array of 2-element Array objects; each nested Array contains a key-value pair from
self
: h = 0, bar: 1, baz: 2 h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]]. -
#to_h ⇒ Object
For an instance of Hash, returns
self
. -
#to_hash ⇒ self
Returns
self
. -
#to_proc ⇒ Proc
Returns a Proc object that maps a key to its value: h = 0, bar: 1, baz: 2 proc = h.to_proc proc.class # => Proc proc.call(:foo) # => 0 proc.call(:bar) # => 1 proc.call(:nosuch) # => nil.
-
#transform_keys(*args) ⇒ Object
Returns a new Hash object; each entry has: * A key provided by the block.
-
#transform_keys!(*args) ⇒ Object
Same as Hash#transform_keys but modifies the receiver in place instead of returning a new hash.
-
#transform_values ⇒ Object
Returns a new Hash object; each entry has: * A key from
self
. -
#transform_values! ⇒ Object
Returns
self
, whose keys are unchanged, and whose values are determined by the given block. -
#update(*args) ⇒ Object
Merges each of
other_hashes
intoself
; returnsself
. -
#has_value?(value) ⇒ Boolean
Returns
true
ifvalue
is a value inself
, otherwisefalse
. -
#values ⇒ Object
Returns a new Array containing all values in
self
: h = 0, bar: 1, baz: 2 h.values # => [0, 1, 2]. -
#values_at(*keys) ⇒ Object
Returns a new Array containing values for the given
keys
: h = 0, bar: 1, baz: 2 h.values_at(:baz, :foo) # => [2, 0].
Methods included from Enumerable
#all?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter_map, #find, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #inject, #lazy, #map, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reverse_each, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #uniq, #zip
Constructor Details
#new(default_value = nil) ⇒ Object #new {|hash, key| ... } ⇒ Object
Returns a new empty Hash object.
The initial default value and initial default proc for the new hash depend on which form above was used. See Default Values.
If neither an argument nor a block given, initializes both the default value and the default proc to nil
:
h = Hash.new
h.default # => nil
h.default_proc # => nil
If argument default_value
given but no block given, initializes the default value to the given default_value
and the default proc to nil
:
h = Hash.new(false)
h.default # => false
h.default_proc # => nil
If a block given but no argument, stores the block as the default proc and sets the default value to nil
:
h = Hash.new {|hash, key| "Default value for #{key}" }
h.default # => nil
h.default_proc.class # => Proc
h[:nosuch] # => "Default value for nosuch"
1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 |
# File 'hash.c', line 1771
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 ⇒ Object .[](hash) ⇒ Object .[]([*2_element_arrays)) ⇒ Object .[](*objects) ⇒ Object
Returns a new Hash object populated with the given objects, if any. See Hash::new.
With no argument, returns a new empty Hash.
When the single given argument is a Hash, returns a new Hash populated with the entries from the given Hash.
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.
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 |
# File 'hash.c', line 1820
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
1940 1941 1942 1943 1944 1945 1946 1947 |
# File 'hash.c', line 1940
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
1918 1919 1920 1921 1922 1923 |
# File 'hash.c', line 1918
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) ⇒ 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.
1897 1898 1899 1900 1901 |
# File 'hash.c', line 1897
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
{
return rb_check_hash_type(hash);
}
|
Instance Method Details
#<(other_hash) ⇒ Boolean
Returns true
if hash
is a proper subset of other_hash
, false
otherwise:
h1 = {foo: 0, bar: 1}
h2 = {foo: 0, bar: 1, baz: 2}
h1 < h2 # => true
h2 < h1 # => false
h1 < h1 # => false
4663 4664 4665 4666 4667 4668 4669 |
# File 'hash.c', line 4663
static VALUE
rb_hash_lt(VALUE hash, VALUE other)
{
other = to_hash(other);
if (RHASH_SIZE(hash) >= RHASH_SIZE(other)) return Qfalse;
return hash_le(hash, other);
}
|
#<=(other_hash) ⇒ Boolean
Returns true
if hash
is a subset of other_hash
, false
otherwise:
h1 = {foo: 0, bar: 1}
h2 = {foo: 0, bar: 1, baz: 2}
h1 <= h2 # => true
h2 <= h1 # => false
h1 <= h1 # => true
4644 4645 4646 4647 4648 4649 4650 |
# File 'hash.c', line 4644
static VALUE
rb_hash_le(VALUE hash, VALUE other)
{
other = to_hash(other);
if (RHASH_SIZE(hash) > RHASH_SIZE(other)) return Qfalse;
return hash_le(hash, other);
}
|
#==(object) ⇒ Boolean
Returns true
if all of the following are true:
-
object
is a Hash object. -
hash
andobject
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
3799 3800 3801 3802 3803 |
# File 'hash.c', line 3799
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
4701 4702 4703 4704 4705 4706 4707 |
# File 'hash.c', line 4701
static VALUE
rb_hash_gt(VALUE hash, VALUE other)
{
other = to_hash(other);
if (RHASH_SIZE(hash) <= RHASH_SIZE(other)) return Qfalse;
return hash_le(other, hash);
}
|
#>=(other_hash) ⇒ Boolean
Returns true
if hash
is a superset of other_hash
, false
otherwise:
h1 = {foo: 0, bar: 1, baz: 2}
h2 = {foo: 0, bar: 1}
h1 >= h2 # => true
h2 >= h1 # => false
h1 >= h1 # => true
4682 4683 4684 4685 4686 4687 4688 |
# File 'hash.c', line 4682
static VALUE
rb_hash_ge(VALUE hash, VALUE other)
{
other = to_hash(other);
if (RHASH_SIZE(hash) < RHASH_SIZE(other)) return Qfalse;
return hash_le(other, hash);
}
|
#[](key) ⇒ Object
Returns the value associated with the given key
, if found:
h = {foo: 0, bar: 1, baz: 2}
h[:foo] # => 0
If key
is not found, returns a default value (see Default Values):
h = {foo: 0, bar: 1, baz: 2}
h[:nosuch] # => nil
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 |
# File 'hash.c', line 2064
VALUE
rb_hash_aref(VALUE hash, VALUE key)
{
st_data_t val;
if (hash_stlike_lookup(hash, key, &val)) {
return (VALUE)val;
}
else {
return rb_hash_default_value(hash, key);
}
}
|
#[]= ⇒ Object
#any? ⇒ Boolean #any?(object) ⇒ Boolean #any? {|key, value| ... } ⇒ Boolean
Returns true
if any element satisfies a given criterion; false
otherwise.
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
4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 |
# File 'hash.c', line 4545
static VALUE
rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
{
VALUE args[2];
args[0] = Qfalse;
rb_check_arity(argc, 0, 1);
if (RHASH_EMPTY_P(hash)) return Qfalse;
if (argc) {
if (rb_block_given_p()) {
rb_warn("given block not used");
}
args[1] = argv[0];
rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
}
else {
if (!rb_block_given_p()) {
/* yields pairs, never false */
return Qtrue;
}
if (rb_block_pair_yield_optimizable())
rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
else
rb_hash_foreach(hash, any_p_i, (VALUE)args);
}
return args[0];
}
|
#assoc(key) ⇒ nil
If the given key
is found, returns a 2-element Array containing that key and its value:
h = {foo: 0, bar: 1, baz: 2}
h.assoc(:bar) # => [:bar, 1]
Returns nil
if key key
is not found.
4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 |
# File 'hash.c', line 4180
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];
}
|
#clear ⇒ self
Removes all hash entries; returns self
.
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 |
# File 'hash.c', line 2837
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;
}
|
#compact ⇒ Object
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}
4356 4357 4358 4359 4360 4361 4362 4363 4364 |
# File 'hash.c', line 4356
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.
4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 |
# File 'hash.c', line 4377
static VALUE
rb_hash_compact_bang(VALUE hash)
{
st_index_t n;
rb_hash_modify_check(hash);
n = RHASH_SIZE(hash);
if (n) {
rb_hash_foreach(hash, delete_if_nil, hash);
if (n != RHASH_SIZE(hash))
return hash;
}
return Qnil;
}
|
#compare_by_identity ⇒ self
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}
4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 |
# File 'hash.c', line 4421
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
Returns true
if #compare_by_identity has been called, false
otherwise.
4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 |
# File 'hash.c', line 4452
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;
}
}
|
#deconstruct_keys(keys) ⇒ Object
4734 4735 4736 4737 4738 |
# File 'hash.c', line 4734
static VALUE
rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
{
return hash;
}
|
#default ⇒ Object #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"
2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 |
# File 'hash.c', line 2182
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.
2209 2210 2211 2212 2213 2214 2215 |
# File 'hash.c', line 2209
static VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
rb_hash_modify_check(hash);
SET_DEFAULT(hash, ifnone);
return ifnone;
}
|
#default_proc ⇒ Proc?
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
2229 2230 2231 2232 2233 2234 2235 2236 |
# File 'hash.c', line 2229
static VALUE
rb_hash_default_proc(VALUE hash)
{
if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
return RHASH_IFNONE(hash);
}
return Qnil;
}
|
#default_proc=(proc) ⇒ Proc
Sets the default proc for self
to proc
: (see Default Values):
h = {}
h.default_proc # => nil
h.default_proc = proc { |hash, key| "Default value for #{key}" }
h.default_proc.class # => Proc
h.default_proc = nil
h.default_proc # => nil
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 |
# File 'hash.c', line 2252
VALUE
rb_hash_set_default_proc(VALUE hash, VALUE proc)
{
VALUE b;
rb_hash_modify_check(hash);
if (NIL_P(proc)) {
SET_DEFAULT(hash, proc);
return proc;
}
b = rb_check_convert_type_with_id(proc, T_DATA, "Proc", idTo_proc);
if (NIL_P(b) || !rb_obj_is_proc(b)) {
rb_raise(rb_eTypeError,
"wrong default_proc type %s (expected Proc)",
rb_obj_classname(proc));
}
proc = b;
SET_PROC_DEFAULT(hash, proc);
return proc;
}
|
#delete(key) ⇒ nil #delete(key) {|key| ... } ⇒ Object
Deletes the entry for the given key
and returns its associated value.
If no block is given and key
is found, deletes the entry and returns the associated value:
h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {:foo=>0, :baz=>2}
If no block given and key
is not found, returns nil
.
If a block is given and key
is found, ignores the block, deletes the entry, and returns the associated value:
h = {foo: 0, bar: 1, baz: 2}
h.delete(:baz) { |key| raise 'Will never happen'} # => 2
h # => {:foo=>0, :bar=>1}
If a block is given and key
is not found, calls the block and returns the block’s return value:
h = {foo: 0, bar: 1, baz: 2}
h.delete(:nosuch) { |key| "Key #{key} not found" } # => "Key nosuch not found"
h # => {:foo=>0, :bar=>1, :baz=>2}
2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 |
# File 'hash.c', line 2385
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_if ⇒ Object
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}
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 |
# File 'hash.c', line 2508
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, *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) # => {: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
4603 4604 4605 4606 4607 4608 4609 4610 4611 |
# File 'hash.c', line 4603
static VALUE
rb_hash_dig(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
self = rb_hash_aref(self, *argv);
if (!--argc) return self;
++argv;
return rb_obj_dig(argc, argv, self, Qnil);
}
|
#each {|key, value| ... } ⇒ self #each_pair {|key, value| ... } ⇒ self #each ⇒ Object #each_pair ⇒ Object
Hash#each is an alias for Hash#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
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 |
# File 'hash.c', line 3148
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_key ⇒ Object
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
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
baz
3095 3096 3097 3098 3099 3100 3101 |
# File 'hash.c', line 3095
static VALUE
rb_hash_each_key(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
rb_hash_foreach(hash, each_key_i, 0);
return hash;
}
|
#each {|key, value| ... } ⇒ self #each_pair {|key, value| ... } ⇒ self #each ⇒ Object #each_pair ⇒ Object
Hash#each is an alias for Hash#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
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 |
# File 'hash.c', line 3148
static VALUE
rb_hash_each_pair(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
if (rb_block_pair_yield_optimizable())
rb_hash_foreach(hash, each_pair_i_fast, 0);
else
rb_hash_foreach(hash, each_pair_i, 0);
return hash;
}
|
#each_value {|value| ... } ⇒ self #each_value ⇒ Object
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
3057 3058 3059 3060 3061 3062 3063 |
# File 'hash.c', line 3057
static VALUE
rb_hash_each_value(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
rb_hash_foreach(hash, each_value_i, 0);
return hash;
}
|
#empty? ⇒ Boolean
Returns true
if there are no hash entries, false
otherwise:
{}.empty? # => true
{foo: 0, bar: 1, baz: 2}.empty? # => false
3020 3021 3022 3023 3024 |
# File 'hash.c', line 3020
static VALUE
rb_hash_empty_p(VALUE hash)
{
return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
}
|
#eql?(object) ⇒ Boolean
Returns true
if all of the following are true:
-
object
is a Hash object. -
hash
andobject
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
3824 3825 3826 3827 3828 |
# File 'hash.c', line 3824
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.
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 |
# File 'hash.c', line 2640
static VALUE
rb_hash_except(int argc, VALUE *argv, VALUE hash)
{
int i;
VALUE key, result;
result = hash_alloc(rb_cHash);
hash_copy(result, hash);
for (i = 0; i < argc; i++) {
key = argv[i];
rb_hash_delete(result, key);
}
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
{}.fetch(:nosuch) # => nil
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.
2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 |
# File 'hash.c', line 2120
static VALUE
rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
{
VALUE key;
st_data_t val;
long block_given;
rb_check_arity(argc, 1, 2);
key = argv[0];
block_given = rb_block_given_p();
if (block_given && argc == 2) {
rb_warn("block supersedes default value argument");
}
if (hash_stlike_lookup(hash, key, &val)) {
return (VALUE)val;
}
else {
if (block_given) {
return rb_yield(key);
}
else if (argc == 1) {
VALUE desc = rb_protect(rb_inspect, key, 0);
if (NIL_P(desc)) {
desc = rb_any_to_s(key);
}
desc = rb_str_ellipsize(desc, 65);
rb_key_err_raise(rb_sprintf("key not found: %"PRIsVALUE, desc), hash, key);
}
else {
return argv[1];
}
}
}
|
#fetch_values(*keys) ⇒ Object #fetch_values(*keys) {|key| ... } ⇒ Object
Returns a new Array containing the values associated with the given keys *keys:
h = {foo: 0, bar: 1, baz: 2}
h.fetch_values(:baz, :foo) # => [2, 0]
Returns a new empty Array if no arguments given.
When a block is given, calls the block with each missing key, treating the block’s return value as the value for that key:
h = {foo: 0, bar: 1, baz: 2}
values = h.fetch_values(:bar, :foo, :bad, :bam) {|key| key.to_s}
values # => [1, 0, "bad", "bam"]
When no block is given, raises an exception if any given key is not found.
2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 |
# File 'hash.c', line 2702
static VALUE
rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
{
VALUE result = rb_ary_new2(argc);
long i;
for (i=0; i<argc; i++) {
rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
}
return result;
}
|
#select {|key, value| ... } ⇒ Object #select ⇒ Object
Hash#filter is an alias for Hash#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}
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 |
# File 'hash.c', line 2740
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! ⇒ Object
Hash#filter! is an alias for Hash#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}
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 |
# File 'hash.c', line 2782
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;
}
|
#flatten ⇒ Object #flatten(level) ⇒ Object
Returns a new Array object that is a 1-dimensional flattening of self
.
By default, nested Arrays are not flattened:
h = {foo: 0, bar: [:bat, 3], baz: 2}
h.flatten # => [:foo, 0, :bar, [:bat, 3], :baz, 2]
Takes the depth of recursive flattening from Integer argument level
:
h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]}
h.flatten(1) # => [:foo, 0, :bar, [:bat, [:baz, [:bat]]]]
h.flatten(2) # => [:foo, 0, :bar, :bat, [:baz, [:bat]]]
h.flatten(3) # => [:foo, 0, :bar, :bat, :baz, [:bat]]
h.flatten(4) # => [:foo, 0, :bar, :bat, :baz, :bat]
When level
is negative, flattens all nested Arrays:
h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]}
h.flatten(-1) # => [:foo, 0, :bar, :bat, :baz, :bat]
h.flatten(-2) # => [:foo, 0, :bar, :bat, :baz, :bat]
When level
is zero, returns the equivalent of #to_a :
h = {foo: 0, bar: [:bat, 3], baz: 2}
h.flatten(0) # => [[:foo, 0], [:bar, [:bat, 3]], [:baz, 2]]
h.flatten(0) == h.to_a # => true
4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 |
# File 'hash.c', line 4295
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
Methods #has_key?, #key?, and #member? are aliases for #include?.
Returns true
if key
is a key in self
, otherwise false
.
3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 |
# File 'hash.c', line 3658
MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
if (hash_stlike_lookup(hash, key, NULL)) {
return Qtrue;
}
else {
return Qfalse;
}
}
|
#has_value?(value) ⇒ Boolean
Returns true
if value
is a value in self
, otherwise false
.
3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 |
# File 'hash.c', line 3688
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];
}
|
#hash ⇒ Integer
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
3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 |
# File 'hash.c', line 3856
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
Methods #has_key?, #key?, and #member? are aliases for #include?.
Returns true
if key
is a key in self
, otherwise false
.
3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 |
# File 'hash.c', line 3658
MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
if (hash_stlike_lookup(hash, key, NULL)) {
return Qtrue;
}
else {
return Qfalse;
}
}
|
#replace(other_hash) ⇒ self
Replaces the entire contents of self
with the contents of other_hash
; returns self
:
h = {foo: 0, bar: 1, baz: 2}
h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4}
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 |
# File 'hash.c', line 2950
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;
}
|
#inspect ⇒ Object Also known as: to_s
Returns a new String containing the hash entries:
h = {foo: 0, bar: 1, baz: 2}
h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}"
Hash#to_s is an alias for Hash#inspect.
3468 3469 3470 3471 3472 3473 3474 |
# File 'hash.c', line 3468
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);
}
|
#invert ⇒ Object
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}
3891 3892 3893 3894 3895 3896 3897 3898 |
# File 'hash.c', line 3891
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_if ⇒ Object
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}
2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 |
# File 'hash.c', line 2813
static VALUE
rb_hash_keep_if(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
rb_hash_foreach(hash, keep_if_i, hash);
}
return hash;
}
|
#key(value) ⇒ nil
Returns the key for the first-found entry with the given value
(see Entry Order):
h = {foo: 0, bar: 2, baz: 2}
h.key(0) # => :foo
h.key(2) # => :bar
Returns nil
if so such value is found.
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 |
# File 'hash.c', line 2298
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
Methods #has_key?, #key?, and #member? are aliases for #include?.
Returns true
if key
is a key in self
, otherwise false
.
3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 |
# File 'hash.c', line 3658
MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
if (hash_stlike_lookup(hash, key, NULL)) {
return Qtrue;
}
else {
return Qfalse;
}
}
|
#keys ⇒ Object
Returns a new Array containing all keys in self
:
h = {foo: 0, bar: 1, baz: 2}
h.keys # => [:foo, :bar, :baz]
3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 |
# File 'hash.c', line 3569
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;
}
|
#length ⇒ Integer #size ⇒ Integer
Returns the count of entries in self
:
{foo: 0, bar: 1, baz: 2}.length # => 3
Hash#length is an alias for Hash#size.
2999 3000 3001 3002 3003 |
# File 'hash.c', line 2999
VALUE
rb_hash_size(VALUE hash)
{
return INT2FIX(RHASH_SIZE(hash));
}
|
#include?(key) ⇒ Boolean #has_key?(key) ⇒ Boolean #key?(key) ⇒ Boolean #member?(key) ⇒ Boolean
Methods #has_key?, #key?, and #member? are aliases for #include?.
Returns true
if key
is a key in self
, otherwise false
.
3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 |
# File 'hash.c', line 3658
MJIT_FUNC_EXPORTED VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
if (hash_stlike_lookup(hash, key, NULL)) {
return Qtrue;
}
else {
return Qfalse;
}
}
|
#merge ⇒ Object #merge(*other_hashes) ⇒ Object #merge(*other_hashes) {|key, old_value, new_value| ... } ⇒ Object
Returns the new Hash formed by merging each of other_hashes
into a copy of self
.
Each argument in other_hashes
must be a Hash.
With arguments and no block:
-
Returns the new Hash object formed by merging each successive Hash in
other_hashes
intoself
. -
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}
4124 4125 4126 4127 4128 |
# File 'hash.c', line 4124
static VALUE
rb_hash_merge(int argc, VALUE *argv, VALUE self)
{
return rb_hash_update(argc, argv, rb_hash_dup(self));
}
|
#merge! ⇒ self #merge!(*other_hashes) ⇒ self #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self
Merges each of other_hashes
into self
; returns self
.
Each argument in other_hashes
must be a Hash.
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}
4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 |
# File 'hash.c', line 4000
static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
int i;
bool block_given = rb_block_given_p();
rb_hash_modify(self);
for (i = 0; i < argc; i++){
VALUE hash = to_hash(argv[i]);
if (block_given) {
rb_hash_foreach(hash, rb_hash_update_block_i, self);
}
else {
rb_hash_foreach(hash, rb_hash_update_i, self);
}
}
return self;
}
|
#rassoc(value) ⇒ nil
Returns a new 2-element Array consisting of the key and value of the first-found entry whose value is ==
to value (see Entry Order):
h = {foo: 0, bar: 1, baz: 1}
h.rassoc(1) # => [:bar, 1]
Returns nil
if no such value found.
4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 |
# File 'hash.c', line 4241
VALUE
rb_hash_rassoc(VALUE hash, VALUE obj)
{
VALUE args[2];
args[0] = obj;
args[1] = Qnil;
rb_hash_foreach(hash, rassoc_i, (VALUE)args);
return args[1];
}
|
#rehash ⇒ self
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.
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 |
# File 'hash.c', line 1978
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| ... } ⇒ Object #reject ⇒ Object
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}
2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 |
# File 'hash.c', line 2578
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! ⇒ Object
Returns self
, whose remaining entries are those for which the block returns false
or nil
:
h = {foo: 0, bar: 1, baz: 2}
h.reject! {|key, value| value < 2 } # => {:baz=>2}
Returns nil
if no entries are removed.
Returns a new Enumerator if no block given:
h = {foo: 0, bar: 1, baz: 2}
e = h.reject! # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject!>
e.each {|key, value| key.start_with?('b') } # => {:foo=>0}
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 |
# File 'hash.c', line 2537
VALUE
rb_hash_reject_bang(VALUE hash)
{
st_index_t n;
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
rb_hash_modify(hash);
n = RHASH_SIZE(hash);
if (!n) return Qnil;
rb_hash_foreach(hash, delete_if_i, hash);
if (n == RHASH_SIZE(hash)) return Qnil;
return hash;
}
|
#replace(other_hash) ⇒ self
Replaces the entire contents of self
with the contents of other_hash
; returns self
:
h = {foo: 0, bar: 1, baz: 2}
h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4}
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 |
# File 'hash.c', line 2950
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| ... } ⇒ Object #select ⇒ Object
Hash#filter is an alias for Hash#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}
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 |
# File 'hash.c', line 2740
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! ⇒ Object
Hash#filter! is an alias for Hash#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}
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 |
# File 'hash.c', line 2782
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;
}
|
#shift ⇒ Array
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).
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 |
# File 'hash.c', line 2436
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);
}
|
#length ⇒ Integer #size ⇒ Integer
Returns the count of entries in self
:
{foo: 0, bar: 1, baz: 2}.length # => 3
Hash#length is an alias for Hash#size.
2999 3000 3001 3002 3003 |
# File 'hash.c', line 2999
VALUE
rb_hash_size(VALUE hash)
{
return INT2FIX(RHASH_SIZE(hash));
}
|
#slice(*keys) ⇒ Object
Returns a new Hash object containing the entries for the given keys
:
h = {foo: 0, bar: 1, baz: 2}
h.slice(:baz, :foo) # => {:baz=>2, :foo=>0}
Any given keys
that are not found are ignored.
2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 |
# File 'hash.c', line 2608
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;
}
|
#store ⇒ Object
#to_a ⇒ Object
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]]
3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 |
# File 'hash.c', line 3413
static VALUE
rb_hash_to_a(VALUE hash)
{
VALUE ary;
ary = rb_ary_new_capa(RHASH_SIZE(hash));
rb_hash_foreach(hash, to_a_i, ary);
return ary;
}
|
#to_h ⇒ self #to_h {|key, value| ... } ⇒ Object
For an instance of Hash, returns self
.
For a subclass of Hash, returns a new Hash containing the content of self
.
When a block is given, returns a new Hash object whose content is based on the block; the block should return a 2-element Array object specifying the key-value pair to be included in the returned Array:
h = {foo: 0, bar: 1, baz: 2}
h1 = h.to_h {|key, value| [value, key] }
h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 |
# File 'hash.c', line 3540
static VALUE
rb_hash_to_h(VALUE hash)
{
if (rb_block_given_p()) {
return rb_hash_to_h_block(hash);
}
if (rb_obj_class(hash) != rb_cHash) {
const VALUE flags = RBASIC(hash)->flags;
hash = hash_dup(hash, rb_cHash, flags & RHASH_PROC_DEFAULT);
}
return hash;
}
|
#to_hash ⇒ self
Returns self
.
3482 3483 3484 3485 3486 |
# File 'hash.c', line 3482
static VALUE
rb_hash_to_hash(VALUE hash)
{
return hash;
}
|
#to_proc ⇒ Proc
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
4728 4729 4730 4731 4732 |
# File 'hash.c', line 4728
static VALUE
rb_hash_to_proc(VALUE hash)
{
return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
}
|
#transform_keys {|key| ... } ⇒ Object #transform_keys(hash2) ⇒ Object #transform_keys(hash2) {|other_key| ... } ⇒ Object #transform_keys ⇒ Object
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}
3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 |
# File 'hash.c', line 3226
static VALUE
rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
{
VALUE result;
struct transform_keys_args transarg = {0};
argc = rb_check_arity(argc, 0, 1);
if (argc > 0) {
transarg.trans = to_hash(argv[0]);
transarg.block_given = rb_block_given_p();
}
else {
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
}
result = rb_hash_new();
if (!RHASH_EMPTY_P(hash)) {
if (transarg.trans) {
transarg.result = result;
rb_hash_foreach(hash, transform_keys_hash_i, (VALUE)&transarg);
}
else {
rb_hash_foreach(hash, transform_keys_i, result);
}
}
return result;
}
|
#transform_keys! {|key| ... } ⇒ self #transform_keys!(hash2) ⇒ self #transform_keys!(hash2) {|other_key| ... } ⇒ self #transform_keys! ⇒ Object
Same as Hash#transform_keys but modifies the receiver in place instead of returning a new hash.
3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 |
# File 'hash.c', line 3266
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_gc_force_recycle(pairs);
rb_hash_clear(new_keys);
rb_gc_force_recycle(new_keys);
}
return hash;
}
|
#transform_values {|value| ... } ⇒ Object #transform_values ⇒ Object
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}
3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 |
# File 'hash.c', line 3352
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);
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);
}
return result;
}
|
#transform_values! {|value| ... } ⇒ self #transform_values! ⇒ Object
Returns self
, whose keys are unchanged, and whose values are determined by the given block.
h = {foo: 0, bar: 1, baz: 2}
h.transform_values! {|value| value * 100} # => {:foo=>0, :bar=>100, :baz=>200}
Returns a new Enumerator if no block given:
h = {foo: 0, bar: 1, baz: 2}
e = h.transform_values! # => #<Enumerator: {:foo=>0, :bar=>100, :baz=>200}:transform_values!>
h1 = e.each {|value| value * 100}
h1 # => {:foo=>0, :bar=>100, :baz=>200}
3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 |
# File 'hash.c', line 3383
static VALUE
rb_hash_transform_values_bang(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
}
return hash;
}
|
#merge! ⇒ self #merge!(*other_hashes) ⇒ self #merge!(*other_hashes) {|key, old_value, new_value| ... } ⇒ self
Merges each of other_hashes
into self
; returns self
.
Each argument in other_hashes
must be a Hash.
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}
4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 |
# File 'hash.c', line 4000
static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
int i;
bool block_given = rb_block_given_p();
rb_hash_modify(self);
for (i = 0; i < argc; i++){
VALUE hash = to_hash(argv[i]);
if (block_given) {
rb_hash_foreach(hash, rb_hash_update_block_i, self);
}
else {
rb_hash_foreach(hash, rb_hash_update_i, self);
}
}
return self;
}
|
#has_value?(value) ⇒ Boolean
Returns true
if value
is a value in self
, otherwise false
.
3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 |
# File 'hash.c', line 3688
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];
}
|
#values ⇒ Object
Returns a new Array containing all values in self
:
h = {foo: 0, bar: 1, baz: 2}
h.values # => [0, 1, 2]
3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 |
# File 'hash.c', line 3613
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) ⇒ Object
Returns a new Array containing values for the given keys
:
h = {foo: 0, bar: 1, baz: 2}
h.values_at(:baz, :foo) # => [2, 0]
The default values are returned for any keys that are not found:
h.values_at(:hello, :foo) # => [nil, 0]
2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 |
# File 'hash.c', line 2670
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;
}
|