From 4d46f366acbba00de1a56c2d3df85fceaaecd1a0 Mon Sep 17 00:00:00 2001 From: vvakame Date: Wed, 9 Aug 2017 19:18:02 +0900 Subject: add method(compact, compact!) and test of Hash to mruby-hash-ext --- mrbgems/mruby-hash-ext/mrblib/hash.rb | 34 ++++++++++++++++++++++++++++++++++ mrbgems/mruby-hash-ext/test/hash.rb | 14 ++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index 846cba9ff..640f7daf5 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -114,6 +114,40 @@ 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.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 } + # + def compact! + result = self.select { |k, v| !v.nil? } + if result.size == self.size + nil + else + self.replace(result) + end + end + ## # call-seq: # hsh.fetch(key [, default] ) -> obj 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") -- cgit v1.2.3 From 6c61a60609e973f3dec00e86ca6f1519ae83e1e3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 9 Aug 2017 21:20:50 +0900 Subject: Implement `Hash#compact!` in C; ref #3769 --- mrbgems/mruby-hash-ext/mrblib/hash.rb | 18 ------------------ mrbgems/mruby-hash-ext/src/hash-ext.c | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index 640f7daf5..73d1fbe6d 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -130,24 +130,6 @@ class Hash result end - ## - # 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 } - # - def compact! - result = self.select { |k, v| !v.nil? } - if result.size == self.size - nil - else - self.replace(result) - end - end - ## # call-seq: # hsh.fetch(key [, default] ) -> 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 -- cgit v1.2.3