Ruby 2.4

Hash

class Hash

Parent:ObjectIncluded modules:Enumerable

哈希是一个字典式的唯一键及其值的集合。也称为关联数组,它们与数组类似,但在数组使用整数作为其索引的情况下,Hash允许您使用任何对象类型。

哈希枚举它们的值的顺序是相应的键被插入。

哈希可以通过使用其隐式形式轻松创建:

grades = { "Jane Doe" => 10, "Jim Doe" => 6 }

哈希允许替代符号键的语法。代替

options = { :font_size => 10, :font_family => "Arial" }

你可以把它写成:

options = { font_size: 10, font_family: "Arial" }

每个已命名的密钥都是您可以在哈希中访问的符号:

options[:font_size] # => 10

哈希也可以通过它的:: new方法创建:

grades = Hash.new grades["Dorothy Doe"] = 9

哈希具有访问哈希中不存在的键时返回的默认值。如果未使用默认值nil。您可以通过将其作为参数发送到:: new来设置默认值

grades = Hash.new(0)

或者使用default =方法:

grades = {"Timmy Doe" => 8} grades.default = 0

在哈希中访问值需要使用其密钥:

puts grades["Jane Doe"] # => 0

常见用途

哈希是表示数据结构的简单方法,例如

books = {} books[:matz] = "The Ruby Programming Language" books[:black] = "The Well-Grounded Rubyist"

散列也常被用作在函数中命名参数的一种方式。请注意,下面不使用括号。如果散列是方法调用的最后一个参数,则不需要花括号,从而创建一个非常干净的界面:

Person.create(name: "John Doe", age: 27) def self.create(params) @name = params[:name] @age = params[:age] end

哈希键

当两个对象的hash值相同且两个对象彼此相同时,两个对象引用相同的散列键eql?

如果重写hasheql?方法以提供有意义的行为,用户定义的类可以用作散列键。默认情况下,单独的实例引用单独的散列键。

典型的实现hash是基于对象的数据,而eql?通常是重写为重写的==方法:

class Book attr_reader :author, :title def initialize(author, title) @author = author @title = title end def ==(other) self.class === other and other.author == @author and other.title == @title end alias eql? == def hash @author.hash ^ @title.hash # XOR end end book1 = Book.new 'matz', 'Ruby in a Nutshell' book2 = Book.new 'matz', 'Ruby in a Nutshell' reviews = {} reviews[book1] = 'Great reference!' reviews[book2] = 'Nice and compact!' reviews.length #=> 1

另见Object#hash和Object#eql?

公共类方法

Hash key, value, ... → new_hash Show source

Hash[ [ key, value, ... ] ] → new_hash

Hash object → new_hash

创建一个用给定对象填充的新散列。

类似于文字。在第一种形式中,键和值是成对出现的,所以必须有偶数个参数。{ key => value, ... }

第二种和第三种形式采用单个参数,它可以是键值对的数组,也可以是可转换为散列的对象。

Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200} Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200} Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}

static VALUE rb_hash_s_create(int argc, VALUE *argv, VALUE klass) { VALUE hash, tmp; int i; if (argc == 1) { tmp = rb_hash_s_try_convert(Qnil, argv[0] if (!NIL_P(tmp)) { hash = hash_alloc(klass if (RHASH(tmp)->ntbl) { RHASH(hash)->ntbl = st_copy(RHASH(tmp)->ntbl } 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)) { #if 0 /* refix in the next release */ rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)", rb_builtin_class_name(e), i #else rb_warn("wrong element type %s at %ld (expected array)", rb_builtin_class_name(e), i rb_warn("ignoring wrong elements is deprecated, remove them explicitly" rb_warn("this causes ArgumentError in the next release" continue; #endif } 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 if (argc > 0) { RHASH(hash)->ntbl = st_init_table_with_size(&objhash, argc / 2 } for (i=0; i<argc; i+=2) { rb_hash_aset(hash, argv[i], argv[i + 1] } return hash; }

new → new_hash Show source

new(obj) → new_hash

new {|hash, key| block } → new_hash

返回一个新的空的散列。如果随后通过与哈希条目不对应的键访问此哈希,则返回的值取决于new用于创建哈希的样式。在第一种形式中,访问返回nil。如果指定obj,则此单个对象将用于所有默认值。如果指定了一个块,将使用散列对象和键调用它,并返回默认值。如果需要,块的责任是将值存储在哈希中。

h = Hash.new("Go Fish") h["a"] = 100 h["b"] = 200 h["a"] #=> 100 h["c"] #=> "Go Fish" # The following alters the single default object h["c"].upcase! #=> "GO FISH" h["d"] #=> "GO FISH" h.keys #=> ["a", "b"] # While this creates a new default object each time h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } h["c"] #=> "Go Fish: c" h["c"].upcase! #=> "GO FISH: C" h["d"] #=> "Go Fish: d" h.keys #=> ["c", "d"]

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

try_convert(obj) → hash or nil Show source

尝试使用#to_hash方法将obj转换为散列。如果因任何原因无法转换obj,则返回转换后的散列或nil 。

Hash.try_convert{1=>2}) # => {1=>2} Hash.try_convert("1=>2") # => nil

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

Public Instance Methods

hash < other → true or false Show source

返回true如果哈希是的子集

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

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 }

hash <= other → true or false Show source

如果散列其他或等于其他的子集,则返回true

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

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 }

hsh == other_hash → true or false Show source

Equality - 如果两个哈希每个包含相同数量的键并且每个键 - 值对等于(根据Object#==)另一个哈希中的相应元素,则两个哈希相等。

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

不会比较每个哈希的顺序。

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

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

hash > other → true or false Show source

如果其他散列的子集,则返回true

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

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 }

hash >= other → true or false Show source

返回true如果其他的子集的哈希或等于哈希

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

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 }

hshkey → value Show source

元素参考 - 检索与对象相对应的对象。如果找不到,则返回默认(详见Hash::new参考资料)。

h = { "a" => 100, "b" => 200 } h["a"] #=> 100 h["c"] #=> nil

VALUE rb_hash_aref(VALUE hash, VALUE key) { st_data_t val; if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { return rb_hash_default_value(hash, key } return (VALUE)val; }

hshkey = value → value Show source

元素分配

将给定的值value与由给定的关键字联系起来key

h = { "a" => 100, "b" => 200 } h["a"] = 9 h["c"] = 4 h #=> {"a"=>9, "b"=>200, "c"=>4} h.store("d", 42) #=> 42 h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}

key在作为密钥使用时不应改变其值(unfrozen String因为密钥将被复制并冻结)。

a = "a" b = "b".freeze h = { a => 100, b => 200 } h.key(100).equal? a #=> false h.key(200).equal? b #=> true

VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val) { int iter_lev = RHASH_ITER_LEV(hash st_table *tbl = RHASH(hash)->ntbl; rb_hash_modify(hash if (!tbl) { if (iter_lev > 0) no_new_key( tbl = hash_tbl(hash } if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) { RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val } else { RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val } return val; }

any? { |(key, value)| block } → true or false Show source

另请参阅Enumerable#any?

static VALUE rb_hash_any_p(VALUE hash) { VALUE ret = Qfalse; if (RHASH_EMPTY_P(hash)) return Qfalse; if (!rb_block_given_p()) { /* yields pairs, never false */ return Qtrue; } if (rb_block_arity() > 1) rb_hash_foreach(hash, any_p_i_fast, (VALUE)&ret else rb_hash_foreach(hash, any_p_i, (VALUE)&ret return ret; }

assoc(obj) → an_array or nil Show source

通过哈希比较obj和密钥使用进行搜索==。返回键值对(两个元素数组)或者nil如果找不到匹配。查看Array#assoc

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

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; table = RHASH(hash)->ntbl; 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 → hsh Show source

hsh中删除所有键值对。

h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200} h.clear #=> {}

VALUE rb_hash_clear(VALUE hash) { rb_hash_modify_check(hash if (!RHASH(hash)->ntbl) return hash; if (RHASH(hash)->ntbl->num_entries > 0) { if (RHASH_ITER_LEV(hash) > 0) rb_hash_foreach(hash, clear_i, 0 else st_clear(RHASH(hash)->ntbl } return hash; }

compact → new_hash Show source

返回删除了零值/密钥对的新散列

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

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! → hsh Show source

从哈希中删除所有的零值。返回散列。

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

static VALUE rb_hash_compact_bang(VALUE hash) { rb_hash_modify_check(hash if (RHASH(hash)->ntbl) { st_index_t n = RHASH(hash)->ntbl->num_entries; rb_hash_foreach(hash, delete_if_nil, hash if (n != RHASH(hash)->ntbl->num_entries) return hash; } return Qnil; }

compare_by_identity → hsh Show source

使hsh通过他们的身份比较它的密钥,即它将认为完全相同的对象作为相同的密钥。

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

static VALUE rb_hash_compare_by_id(VALUE hash) { if (rb_hash_compare_by_id_p(hash)) return hash; rb_hash_modify(hash RHASH(hash)->ntbl->type = &identhash; rb_hash_rehash(hash return hash; }

compare_by_identity? → true or false Show source

如果hsh将按其身份比较其键,则返回true。另见Hash#compare_by_identity

VALUE rb_hash_compare_by_id_p(VALUE hash) { if (!RHASH(hash)->ntbl) return Qfalse; if (RHASH(hash)->ntbl->type == &identhash) { return Qtrue; } return Qfalse; }

default(key=nil) → obj Show source

返回默认值,如果key不存在于hsh中,则返回hsh返回的值。另见Hash::newHash#default=

h = Hash.new #=> {} h.default #=> nil h.default(2) #=> nil h = Hash.new("cat") #=> {} h.default #=> "cat" h.default(2) #=> "cat" h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {} h.default #=> nil h.default(2) #=> 20

static VALUE rb_hash_default(int argc, VALUE *argv, VALUE hash) { VALUE args[2], ifnone; rb_check_arity(argc, 0, 1 ifnone = RHASH_IFNONE(hash if (FL_TEST(hash, HASH_PROC_DEFAULT)) { if (argc == 0) return Qnil; args[0] = hash; args[1] = argv[0]; return rb_funcallv(ifnone, id_yield, 2, args } return ifnone; }

default = obj → obj Show source

设置默认值,即散列中不存在的键所返回的值。无法将默认设置为Proc每个键查找时执行的默认值。

h = { "a" => 100, "b" => 200 } h.default = "Go fish" h["a"] #=> 100 h["z"] #=> "Go fish" # This doesn't do what you might hope... h.default = proc do |hash, key| hash[key] = key + key end h[2] #=> #<Proc:0x401b3948@-:6> h["cat"] #=> #<Proc:0x401b3948@-:6>

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

default_proc → anObject Show source

如果Hash::new使用块调用,则返回该块,否则返回nil

h = Hash.new {|h,k| h[k] = k*k } #=> {} p = h.default_proc #=> #<Proc:0x401b3d08@-:1> a = [] #=> [] p.call(a, 2) a #=> [nil, nil, 4]

static VALUE rb_hash_default_proc(VALUE hash) { if (FL_TEST(hash, HASH_PROC_DEFAULT)) { return RHASH_IFNONE(hash } return Qnil; }

default_proc = proc_obj or nil Show source

设置在每个失败的密钥查找中执行的默认proc。

h.default_proc = proc do |hash, key| hash[key] = key + key end h[2] #=> 4 h["cat"] #=> "catcat"

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(proc, T_DATA, "Proc", "to_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) → value Show source

delete(key) {| key | block } → value

删除键值对并从键值等于键的hsh返回值。如果找不到密钥,则返回nil。如果给出可选的代码并且未找到密钥,则传入密钥并返回的结果。

h = { "a" => 100, "b" => 200 } h.delete("a") #=> 100 h.delete("z") #=> nil h.delete("z") { |el| "#{el} not found" } #=> "z not found"

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 | block } → hsh Show source

delete_if → an_enumerator

删除从每一个键-值对HSH针对的计算结果为true

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200, "c" => 300 } h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}

VALUE rb_hash_delete_if(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size rb_hash_modify_check(hash if (RHASH(hash)->ntbl) rb_hash_foreach(hash, delete_if_i, hash return hash; }

dig(key, ...) → object Show source

通过在每个步骤调用来提取由关键对象序列指定的嵌套值dignil如果有任何中间步骤则返回nil

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

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 | block } → hsh Show source

each_pair {| key, value | block } → hsh

each → an_enumerator

each_pair → an_enumerator

hsh中的每个键调用一次,传递键值对作为参数。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200 } h.each {|key, value| puts "#{key} is #{value}" }

produces:

a is 100 b is 200

static VALUE rb_hash_each_pair(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size if (rb_block_arity() > 1) rb_hash_foreach(hash, each_pair_i_fast, 0 else rb_hash_foreach(hash, each_pair_i, 0 return hash; }

each_key {| key | block } → hsh Show source

each_key → an_enumerator

hsh中的每个键调用一次,将该键作为参数传递。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200 } h.each_key {|key| puts key }

produces:

a b

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_pair {| key, value | block } → hsh Show source

each_pair → an_enumerator

hsh中的每个键调用一次,传递键值对作为参数。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200 } h.each {|key, value| puts "#{key} is #{value}" }

produces:

a is 100 b is 200

static VALUE rb_hash_each_pair(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size if (rb_block_arity() > 1) rb_hash_foreach(hash, each_pair_i_fast, 0 else rb_hash_foreach(hash, each_pair_i, 0 return hash; }

each_value {| value | block } → hsh Show source

each_value → an_enumerator

hsh中的每个键调用一次,并将该值作为参数传递。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200 } h.each_value {|value| puts value }

produces:

100 200

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? → true or false Show source

如果hsh不包含键值对,则返回true

{}.empty? #=> true

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

eql?(other) → true or false Show source

如果散列其他散列具有相同内容,则返回true散列值。不会比较每个哈希的顺序。

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

fetch(key , default ) → obj Show source

fetch(key) {| key | block } → obj

从给定密钥的散列中返回一个值。如果找不到密钥,则有以下几种选择:如果没有其他参数,则会引发KeyError异常;如果给出了默认值,那么将返回;如果指定了可选的代码块,那么将运行该代码块并返回其结果。

h = { "a" => 100, "b" => 200 } h.fetch("a") #=> 100 h.fetch("z", "go fish") #=> "go fish" h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"

以下示例显示如果未找到密钥并且未提供默认值,则会引发异常。

h = { "a" => 100, "b" => 200 } h.fetch("z")

produces:

prog.rb:2:in `fetch': key not found (KeyError) from prog.rb:2

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 (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { if (block_given) return rb_yield(key 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_raise(rb_eKeyError, "key not found: %"PRIsVALUE, desc } return argv[1]; } return (VALUE)val; }

fetch_values(key, ...) → array Show source

fetch_values(key, ...) { |key| block } → array

返回包含与给定键相关联的值的数组,KeyError但当找不到其中一个键时也会返回。另见Hash#values_atHash#fetch

h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } h.fetch_values("cow", "cat") #=> ["bovine", "feline"] h.fetch_values("cow", "bird") # raises KeyError h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]

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

flatten → an_array Show source

flatten(level) → an_array

返回一个新的数组,该哈希是一维平坦化的。也就是说,对于数组中的每个键或值,将其元素提取到新数组中。与Array#flatten不同,此方法默认情况下不会以递归方式平坦化。可选的参数级别决定了要展平的递归级别

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

static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash) { VALUE ary; if (argc) { int level = NUM2INT(*argv 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 if (level - 1 > 0) { *argv = INT2FIX(level - 1 rb_funcallv(ary, id_flatten_bang, argc, argv } else if (level < 0) { 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; }

has_key?(key) → true or false Show source

返回true给定的键是否存在于hsh中

h = { "a" => 100, "b" => 200 } h.has_key?("a") #=> true h.has_key?("z") #=> false

请注意,include?member?使用不测试成员平等==的做其他可枚举。

另请参阅Enumerable #include?

VALUE rb_hash_has_key(VALUE hash, VALUE key) { if (!RHASH(hash)->ntbl) return Qfalse; if (st_lookup(RHASH(hash)->ntbl, key, 0)) { return Qtrue; } return Qfalse; }

has_value?(value) → true or false Show source

返回true给定值是否存在于hsh中的某个键。

h = { "a" => 100, "b" => 200 } h.value?(100) #=> true h.value?(999) #=> false

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 Show source

计算此散列的散列码。两个具有相同内容的散列将具有相同的散列码(并将使用比较eql?)。

另请参阅Object#hash。

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) → true or false Show source

返回true给定的键是否存在于hsh中

h = { "a" => 100, "b" => 200 } h.has_key?("a") #=> true h.has_key?("z") #=> false

请注意,include?member?使用不测试成员平等==的做其他可枚举。

另请参阅Enumerable #include?

VALUE rb_hash_has_key(VALUE hash, VALUE key) { if (!RHASH(hash)->ntbl) return Qfalse; if (st_lookup(RHASH(hash)->ntbl, key, 0)) { return Qtrue; } return Qfalse; }

to_s → string Show source

inspect → string

以字符串形式返回此散列的内容。

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"

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 }

另外别名为:to_s

invert → new_hash Show source

返回通过使用hsh的值作为键创建的新散列,并将键作为值创建。如果在hsh中已经存在具有相同值的密钥,则使用定义的最后一个密钥,较早的值将被丢弃。

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

如果没有具有相同值的键,则#invert是合成的。

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

可以通过比较反转散列的大小来测试条件,即不具有相同值的键。

# no key with the same value h = { a: 1, b: 3, c: 4 } h.size == h.invert.size #=> true # two (or more) keys has the same value h = { a: 1, b: 3, c: 1 } h.size == h.invert.size #=> false

static VALUE rb_hash_invert(VALUE hash) { VALUE h = rb_hash_new( rb_hash_foreach(hash, rb_hash_invert_i, h return h; }

keep_if {| key, value | block } → hsh Show source

keep_if → an_enumerator

删除从每一个键-值对HSH为哪些评估为假。

如果没有给出块,则返回一个枚举器。

VALUE rb_hash_keep_if(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size rb_hash_modify_check(hash if (RHASH(hash)->ntbl) rb_hash_foreach(hash, keep_if_i, hash return hash; }

key(value) → key Show source

返回给定值发生的关键。如果未找到该值,则返回nil

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 } h.key(200) #=> "b" h.key(300) #=> "c" h.key(999) #=> nil

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

key?(key) → true or false Show source

返回true给定的键是否存在于hsh中

h = { "a" => 100, "b" => 200 } h.has_key?("a") #=> true h.has_key?("z") #=> false

请注意,include?member?使用不测试成员平等==的做其他可枚举。

另请参阅Enumerable #include?

VALUE rb_hash_has_key(VALUE hash, VALUE key) { if (!RHASH(hash)->ntbl) return Qfalse; if (st_lookup(RHASH(hash)->ntbl, key, 0)) { return Qtrue; } return Qfalse; }

keys → array Show source

返回一个新数组,其中填充了该散列中的键。另见Hash#values

h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 } h.keys #=> ["a", "b", "c", "d"]

VALUE rb_hash_keys(VALUE hash) { VALUE keys; st_index_t size = RHASH_SIZE(hash keys = rb_ary_new_capa(size if (size == 0) return keys; if (ST_DATA_COMPATIBLE_P(VALUE)) { st_table *table = RHASH(hash)->ntbl; rb_gc_writebarrier_remember(keys RARRAY_PTR_USE(keys, ptr, { size = st_keys_check(table, ptr, size, Qundef } rb_ary_set_len(keys, size } else { rb_hash_foreach(hash, keys_i, keys } return keys; }

length → integer Show source

返回散列中的键值对的数量。

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 } h.length #=> 4 h.delete("a") #=> 200 h.length #=> 3

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

member?(key) → true or false Show source

返回true给定的键是否存在于hsh中

h = { "a" => 100, "b" => 200 } h.has_key?("a") #=> true h.has_key?("z") #=> false

请注意,include?member?使用不测试成员平等==的做其他可枚举。

另请参阅Enumerable #include?

VALUE rb_hash_has_key(VALUE hash, VALUE key) { if (!RHASH(hash)->ntbl) return Qfalse; if (st_lookup(RHASH(hash)->ntbl, key, 0)) { return Qtrue; } return Qfalse; }

merge(other_hash) → new_hash Show source

merge(other_hash){|key, oldval, newval| block} → new_hash

返回包含内容的新的哈希other_hash和内容HSH。如果未指定块,则具有重复键的条目的值将是other_hash的值。否则,每个重复键的值都是通过用键调用块来确定的,它的值在hsh中,值在other_hash中

h1 = { "a" => 100, "b" => 200 } h2 = { "b" => 254, "c" => 300 } h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300} h1.merge(h2){|key, oldval, newval| newval - oldval} #=> {"a"=>100, "b"=>54, "c"=>300} h1 #=> {"a"=>100, "b"=>200}

static VALUE rb_hash_merge(VALUE hash1, VALUE hash2) { return rb_hash_update(rb_obj_dup(hash1), hash2 }

merge!(other_hash) → hsh Show source

merge!(other_hash){|key, oldval, newval| block} → hsh

other_hash的内容添加到hsh。如果未指定块,则使用other_hash中的值覆盖具有重复键的条目,否则每个重复键的值由通过键调用块确定,其值在hsh中,值在other_hash中确定

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

static VALUE rb_hash_update(VALUE hash1, VALUE hash2) { rb_hash_modify(hash1 hash2 = to_hash(hash2 if (rb_block_given_p()) { rb_hash_foreach(hash2, rb_hash_update_block_i, hash1 } else { rb_hash_foreach(hash2, rb_hash_update_i, hash1 } return hash1; }

rassoc(obj) → an_array or nil Show source

通过hash比较obj和使用的值进行搜索==。返回匹配的第一个键 - 值对(双元素数组)。另见Array#rassoc

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

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 → hsh Show source

根据每个密钥的当前散列值重建散列。如果关键对象的值自插入后发生了更改,则此方法将重新索引hsh。如果Hash#rehash在迭代器遍历散列时调用,则迭代器RuntimeError中将引发一个。

a = [ "a", "b" ] c = [ "c", "d" ] h = { a => 100, c => 300 } h[a] #=> 100 a[0] = "z" h[a] #=> nil h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300} h[a] #=> 100

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(hash)->ntbl) return hash; tmp = hash_alloc(0 tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries RHASH(tmp)->ntbl = tbl; rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl st_free_table(RHASH(hash)->ntbl RHASH(hash)->ntbl = tbl; RHASH(tmp)->ntbl = 0; return hash; }

reject {|key, value| block} → a_hash Show source

reject → an_enumerator

返回由该块返回false的条目组成的新散列。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200, "c" => 300 } h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300} h.reject {|k,v| v > 100} #=> {"a" => 100}

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 | block } → hsh or nil Show source

reject! → an_enumerator

等同于Hash#delete_if,但如果没有更改,则返回nil

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(hash)->ntbl->num_entries) return Qnil; return hash; }

replace(other_hash) → hsh Show source

other_hash的内容替换hsh的内容。

h = { "a" => 100, "b" => 200 } h.replace{ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}

static VALUE rb_hash_replace(VALUE hash, VALUE hash2) { st_table *table2; rb_hash_modify_check(hash if (hash == hash2) return hash; hash2 = to_hash(hash2 COPY_DEFAULT(hash, hash2 table2 = RHASH(hash2)->ntbl; rb_hash_clear(hash if (table2) hash_tbl(hash)->type = table2->type; rb_hash_foreach(hash2, replace_i, hash return hash; }

select {|key, value| block} → a_hash Show source

select → an_enumerator

返回由该块返回true的条目组成的新散列。

如果没有给出块,则返回一个枚举器。

h = { "a" => 100, "b" => 200, "c" => 300 } h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300} h.select {|k,v| v < 200} #=> {"a" => 100}

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 | block } → hsh or nil Show source

select! → an_enumerator

等同于Hash#keep_if,但如果没有更改,则返回nil

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 if (!RHASH(hash)->ntbl) return Qnil; n = RHASH(hash)->ntbl->num_entries; rb_hash_foreach(hash, keep_if_i, hash if (n == RHASH(hash)->ntbl->num_entries) return Qnil; return hash; }

shift → anArray or obj Show source

hsh中删除键值对,并将其作为两项数组[ 键,值 ]或散列的默认值(如果散列为空)返回。

h = { 1 => "a", 2 => "b", 3 => "c" } h.shift #=> [1, "a"] h #=> {2=>"b", 3=>"c"}

static VALUE rb_hash_shift(VALUE hash) { struct shift_var var; rb_hash_modify_check(hash if (RHASH(hash)->ntbl) { var.key = Qundef; if (RHASH_ITER_LEV(hash) == 0) { if (st_shift(RHASH(hash)->ntbl, &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 }

size → integer Show source

返回散列中的键值对的数量。

h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 } h.length #=> 4 h.delete("a") #=> 200 h.length #=> 3

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

store(key, value) → value Show source

元素分配

将给定的值value与由key给定的关键字联系起来。

h = { "a" => 100, "b" => 200 } h["a"] = 9 h["c"] = 4 h #=> {"a"=>9, "b"=>200, "c"=>4} h.store("d", 42) #=> 42 h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}

key在作为密钥使用时不应改变其值(unfrozen String因为密钥将被复制并冻结)。

a = "a" b = "b".freeze h = { a => 100, b => 200 } h.key(100).equal? a #=> false h.key(200).equal? b #=> true

VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val) { int iter_lev = RHASH_ITER_LEV(hash st_table *tbl = RHASH(hash)->ntbl; rb_hash_modify(hash if (!tbl) { if (iter_lev > 0) no_new_key( tbl = hash_tbl(hash } if (tbl->type == &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; }

to_a → array Show source

hsh转换为[ 键值 数组的嵌套数组]

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } h.to_a #=> [["c", 300], ["a", 100], ["d", 400]]

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 OBJ_INFECT(ary, hash return ary; }

to_h → hsh or new_hash Show source

返回self。如果在哈希的子类上调用,则将接收器转换为哈希对象。

static VALUE rb_hash_to_h(VALUE hash) { if (rb_obj_class(hash) != rb_cHash) { const VALUE flags = RBASIC(hash)->flags; hash = hash_dup(hash, rb_cHash, flags & HASH_PROC_DEFAULT } return hash; }

to_hash → hsh Show source

返回self

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

to_proc() Show source

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

to_s()

Alias for: inspect

transform_values {|value| block } → hsh Show source

transform_values → an_enumerator

为每个值返回一次运行块的结果。此方法不会更改密钥。

h = { a: 1, b: 2, c: 3 } h.transform_values {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 } h.transform_values(&:to_s) #=> { a: "1", b: "2", c: "3" } h.transform_values.with_index {|v, i| "#{v}.#{i}" } #=> { a: "1.0", b: "2.1", c: "3.2" }

如果没有给出块,则返回一个枚举器。

static VALUE rb_hash_transform_values(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, transform_values_i, result } return result; }

transform_values! {|value| block } → hsh Show source

transform_values! → an_enumerator

为每个值返回一次运行块的结果。此方法不会更改密钥。

h = { a: 1, b: 2, c: 3 } h.transform_values! {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 } h.transform_values!(&:to_s) #=> { a: "1", b: "2", c: "3" } h.transform_values!.with_index {|v, i| "#{v}.#{i}" } #=> { a: "1.0", b: "2.1", c: "3.2" }

如果没有给出块,则返回一个枚举器。

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(hash)->ntbl) rb_hash_foreach(hash, transform_values_i, hash return hash; }

update(other_hash) → hsh Show source

update(other_hash){|key, oldval, newval| block} → hsh

other_hash的内容添加到hsh。如果未指定块,则使用other_hash中的值覆盖具有重复键的条目,否则每个重复键的值由通过键调用块确定,其值在hsh中,值在other_hash中确定

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

static VALUE rb_hash_update(VALUE hash1, VALUE hash2) { rb_hash_modify(hash1 hash2 = to_hash(hash2 if (rb_block_given_p()) { rb_hash_foreach(hash2, rb_hash_update_block_i, hash1 } else { rb_hash_foreach(hash2, rb_hash_update_i, hash1 } return hash1; }

value?(value) → true or false Show source

返回true给定值是否存在于hsh中的某个键。

h = { "a" => 100, "b" => 200 } h.value?(100) #=> true h.value?(999) #=> false

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 → array Show source

hsh的值返回一个新的数组。另见Hash#keys

h = { "a" => 100, "b" => 200, "c" => 300 } h.values #=> [100, 200, 300]

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)) { st_table *table = RHASH(hash)->ntbl; rb_gc_writebarrier_remember(values RARRAY_PTR_USE(values, ptr, { size = st_values_check(table, ptr, size, Qundef } rb_ary_set_len(values, size } else { rb_hash_foreach(hash, values_i, values } return values; }

values_at(key, ...) → array Show source

返回包含与给定键相关的值的数组。另见Hash.select

h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } h.values_at("cow", "cat") #=> ["bovine", "feline"]

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