summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-hash-ext
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-12-25 15:40:10 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-12-25 23:43:37 +0900
commit421819dc2ce42ae32e67d0d2151eed50f7c12e93 (patch)
tree9b658ee0c67450059f715ce404d628405fe6db08 /mrbgems/mruby-hash-ext
parentdf68a3345de9b5b711b1f720dad1cd0109854188 (diff)
downloadmruby-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.c40
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb6
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