diff options
| -rw-r--r-- | mrbgems/mruby-enum-ext/mrblib/enum.rb | 29 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-ext/test/enum.rb | 9 |
2 files changed, 38 insertions, 0 deletions
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index a228abb0b..4f5166b03 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -439,4 +439,33 @@ module Enumerable end true end + + ## + # call-seq: + # enum.one? [{ |obj| block }] -> true or false + # + # Passes each element of the collection to the given block. The method + # returns <code>true</code> if the block returns <code>true</code> + # exactly once. If the block is not given, <code>one?</code> will return + # <code>true</code> only if exactly one of the collection members is + # true. + # + # %w(ant bear cat).one? { |word| word.length == 4 } #=> true + # %w(ant bear cat).one? { |word| word.length > 4 } #=> false + # %w(ant bear cat).one? { |word| word.length < 4 } #=> false + # [nil, true, 99].one? #=> false + # [nil, true, false].one? #=> true + # + + def one?(&block) + count = 0 + self.each do |*val| + if block + count += 1 if block.call(*val) + else + count += 1 if val.__svalue + end + end + count == 1 ? true : false + end end diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb index d0f47448f..813c9bf4e 100644 --- a/mrbgems/mruby-enum-ext/test/enum.rb +++ b/mrbgems/mruby-enum-ext/test/enum.rb @@ -102,3 +102,12 @@ assert("Enumerable#none?") do assert_true [nil, false].none? assert_false [nil, true].none? end + +assert("Enumerable#one?") do + assert_true %w(ant bear cat).one? { |word| word.length == 4 } + assert_false %w(ant bear cat).one? { |word| word.length > 4 } + assert_false %w(ant bear cat).one? { |word| word.length < 4 } + assert_false [nil, true, 99].one? + assert_true [nil, true, false].one? +end + |
