diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-12-25 15:40:10 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-12-25 23:43:37 +0900 |
| commit | 421819dc2ce42ae32e67d0d2151eed50f7c12e93 (patch) | |
| tree | 9b658ee0c67450059f715ce404d628405fe6db08 /mrbgems/mruby-hash-ext | |
| parent | df68a3345de9b5b711b1f720dad1cd0109854188 (diff) | |
| download | mruby-421819dc2ce42ae32e67d0d2151eed50f7c12e93.tar.gz mruby-421819dc2ce42ae32e67d0d2151eed50f7c12e93.zip | |
Add `Hash#slice` [Ruby 2.5]
Diffstat (limited to 'mrbgems/mruby-hash-ext')
| -rw-r--r-- | mrbgems/mruby-hash-ext/src/hash-ext.c | 40 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/test/hash.rb | 6 |
2 files changed, 46 insertions, 0 deletions
diff --git a/mrbgems/mruby-hash-ext/src/hash-ext.c b/mrbgems/mruby-hash-ext/src/hash-ext.c index 952f2eb64..6619f5268 100644 --- a/mrbgems/mruby-hash-ext/src/hash-ext.c +++ b/mrbgems/mruby-hash-ext/src/hash-ext.c @@ -72,6 +72,45 @@ hash_compact_bang(mrb_state *mrb, mrb_value hash) return hash; } +/* + * call-seq: + * hsh.slice(*keys) -> a_hash + * + * Returns a hash containing only the given keys and their values. + * + * h = { a: 100, b: 200, c: 300 } + * h.slice(:a) #=> {:a=>100} + * h.slice(:b, :c, :d) #=> {:b=>200, :c=>300} + */ +static mrb_value +hash_slice(mrb_state *mrb, mrb_value hash) +{ + khash_t(ht) *h = RHASH_TBL(hash); + mrb_value *argv, result; + mrb_int argc, i; + khiter_t k; + int ai; + + mrb_get_args(mrb, "*", &argv, &argc); + if (argc == 0 || h == NULL) { + return mrb_hash_new_capa(mrb, argc); + } + result = mrb_hash_new_capa(mrb, argc); + ai = mrb_gc_arena_save(mrb); + for (i = 0; i < argc; i++) { + mrb_value key = argv[i]; + + k = kh_get(ht, mrb, h, key); + if (k != kh_end(h)) { + mrb_value val = kh_value(h, k).v; + + mrb_hash_set(mrb, result, key, val); + } + mrb_gc_arena_restore(mrb, ai); + } + return result; +} + void mrb_mruby_hash_ext_gem_init(mrb_state *mrb) { @@ -80,6 +119,7 @@ mrb_mruby_hash_ext_gem_init(mrb_state *mrb) h = mrb->hash_class; mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY()); mrb_define_method(mrb, h, "compact!", hash_compact_bang, MRB_ARGS_NONE()); + mrb_define_method(mrb, h, "slice", hash_slice, MRB_ARGS_ANY()); } void diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb index 183cecfce..269da800d 100644 --- a/mrbgems/mruby-hash-ext/test/hash.rb +++ b/mrbgems/mruby-hash-ext/test/hash.rb @@ -292,3 +292,9 @@ assert("Hash#transform_values") do assert_equal(h, h.transform_values!{|v|v.to_s}) assert_equal({a: "1", b: "2", c: "3"}, h) end + +assert("Hash#slice") do + h = { a: 100, b: 200, c: 300 } + assert_equal({:a=>100}, h.slice(:a)) + assert_equal({:b=>200, :c=>300}, h.slice(:b, :c, :d)) +end |
