summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-08-09 21:21:31 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-08-09 21:21:31 +0900
commit24c345fe5c68a3f0cd4d16e84c8bf6ed93cedce8 (patch)
tree4ca852347e8c94c8ab6114a0ff98657f9450e0f4
parentf9c3ebd29d7410be209b3f22b9923f0f81f0141d (diff)
parent6c61a60609e973f3dec00e86ca6f1519ae83e1e3 (diff)
downloadmruby-24c345fe5c68a3f0cd4d16e84c8bf6ed93cedce8.tar.gz
mruby-24c345fe5c68a3f0cd4d16e84c8bf6ed93cedce8.zip
Merge branch 'vvakame-add-hash-compact'
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb16
-rw-r--r--mrbgems/mruby-hash-ext/src/hash-ext.c36
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb14
3 files changed, 66 insertions, 0 deletions
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
index 846cba9ff..73d1fbe6d 100644
--- a/mrbgems/mruby-hash-ext/mrblib/hash.rb
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -115,6 +115,22 @@ class Hash
alias update merge!
##
+ # call-seq:
+ # hsh.compact -> new_hsh
+ #
+ # Returns a new hash with the nil values/key pairs removed
+ #
+ # h = { a: 1, b: false, c: nil }
+ # h.compact #=> { a: 1, b: false }
+ # h #=> { a: 1, b: false, c: nil }
+ #
+ def compact
+ result = self.dup
+ result.compact!
+ result
+ end
+
+ ##
# call-seq:
# hsh.fetch(key [, default] ) -> obj
# hsh.fetch(key) {| key | block } -> obj
diff --git a/mrbgems/mruby-hash-ext/src/hash-ext.c b/mrbgems/mruby-hash-ext/src/hash-ext.c
index 61abc080d..53178ffe4 100644
--- a/mrbgems/mruby-hash-ext/src/hash-ext.c
+++ b/mrbgems/mruby-hash-ext/src/hash-ext.c
@@ -36,6 +36,41 @@ hash_values_at(mrb_state *mrb, mrb_value hash)
return result;
}
+/*
+ * call-seq:
+ * hsh.compact! -> hsh
+ *
+ * Removes all nil values from the hash. Returns the hash.
+ *
+ * h = { a: 1, b: false, c: nil }
+ * h.compact! #=> { a: 1, b: false }
+ */
+static mrb_value
+hash_compact_bang(mrb_state *mrb, mrb_value hash)
+{
+ khiter_t k;
+ khash_t(ht) *h = RHASH_TBL(hash);
+ mrb_int n = -1;
+
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ mrb_value val = kh_value(h, k).v;
+ khiter_t k2;
+
+ if (mrb_nil_p(val)) {
+ kh_del(ht, mrb, h, k);
+ n = kh_value(h, k).n;
+ for (k2 = kh_begin(h); k2 != kh_end(h); k2++) {
+ if (!kh_exist(h, k2)) continue;
+ if (kh_value(h, k2).n > n) kh_value(h, k2).n--;
+ }
+ }
+ }
+ }
+ if (n < 0) return mrb_nil_value();
+ return hash;
+}
+
void
mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
{
@@ -43,6 +78,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());
}
void
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
index 2ae88c307..ca4e346fb 100644
--- a/mrbgems/mruby-hash-ext/test/hash.rb
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -82,6 +82,20 @@ assert('Hash#values_at') do
assert_equal keys, h.values_at(*keys)
end
+assert('Hash#compact') do
+ h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+ assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
+ assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
+end
+
+assert('Hash#compact!') do
+ h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+ h.compact!
+ assert_equal({ "cat" => "feline", "cow" => false }, h)
+end
+
assert('Hash#fetch') do
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
assert_equal "feline", h.fetch("cat")