summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb65
-rw-r--r--mrbgems/mruby-enum-ext/test/enum.rb12
-rw-r--r--mrbgems/mruby-enumerator/test/enumerator.rb14
-rw-r--r--mrblib/hash.rb8
4 files changed, 97 insertions, 2 deletions
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
index 873de1fbc..a228abb0b 100644
--- a/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -374,4 +374,69 @@ module Enumerable
end
[min, max]
end
+
+ ##
+ # call-seq:
+ # enum.minmax_by { |obj| block } -> [min, max]
+ # enum.minmax_by -> an_enumerator
+ #
+ # Returns a two element array containing the objects in
+ # <i>enum</i> that correspond to the minimum and maximum values respectively
+ # from the given block.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # %w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
+
+ def minmax_by(&block)
+ max = nil
+ max_cmp = nil
+ min = nil
+ min_cmp = nil
+ first = true
+
+ self.each do |*val|
+ if first
+ max = min = val.__svalue
+ max_cmp = min_cmp = block.call(*val)
+ first = false
+ else
+ if (cmp = block.call(*val)) > max_cmp
+ max = val.__svalue
+ max_cmp = cmp
+ end
+ if (cmp = block.call(*val)) < min_cmp
+ min = val.__svalue
+ min_cmp = cmp
+ end
+ end
+ end
+ [min, max]
+ end
+
+ ##
+ # call-seq:
+ # enum.none? [{ |obj| block }] -> true or false
+ #
+ # Passes each element of the collection to the given block. The method
+ # returns <code>true</code> if the block never returns <code>true</code>
+ # for all elements. If the block is not given, <code>none?</code> will return
+ # <code>true</code> only if none of the collection members is true.
+ #
+ # %w(ant bear cat).none? { |word| word.length == 5 } #=> true
+ # %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
+ # [].none? #=> true
+ # [nil, false].none? #=> true
+ # [nil, true].none? #=> false
+
+ def none?(&block)
+ self.each do |*val|
+ if block
+ return false if block.call(*val)
+ else
+ return false if val.__svalue
+ end
+ end
+ true
+ end
end
diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb
index 2f7ed7aaa..d0f47448f 100644
--- a/mrbgems/mruby-enum-ext/test/enum.rb
+++ b/mrbgems/mruby-enum-ext/test/enum.rb
@@ -90,3 +90,15 @@ assert("Enumerable#minmax") do
assert_equal ["albatross", "horse"], a.minmax
assert_equal ["dog", "albatross"], a.minmax { |a, b| a.length <=> b.length }
end
+
+assert("Enumerable#minmax_by") do
+ assert_equal ["dog", "albatross"], %w(albatross dog horse).minmax_by { |x| x.length }
+end
+
+assert("Enumerable#none?") do
+ assert_true %w(ant bear cat).none? { |word| word.length == 5 }
+ assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
+ assert_true [].none?
+ assert_true [nil, false].none?
+ assert_false [nil, true].none?
+end
diff --git a/mrbgems/mruby-enumerator/test/enumerator.rb b/mrbgems/mruby-enumerator/test/enumerator.rb
index fdee06450..6c224eaa3 100644
--- a/mrbgems/mruby-enumerator/test/enumerator.rb
+++ b/mrbgems/mruby-enumerator/test/enumerator.rb
@@ -494,6 +494,20 @@ assert 'Hash#each_value' do
assert_equal [1,2], {a:1,b:2}.each_value.to_a.sort
end
+assert 'Hash#select' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.select.with_index {|a,b| a[1] == 4}
+ assert_equal({3=>4}, hret)
+ assert_equal({1=>2,3=>4,5=>6}, h)
+end
+
+assert 'Hash#select!' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.select!.with_index {|a,b| a[1] == 4}
+ assert_equal h, hret
+ assert_equal({3=>4}, h)
+end
+
assert 'Range#each' do
a = (1..5)
b = a.each
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index cd6ba8935..491d2a0ee 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -162,10 +162,12 @@ class Hash
# 1.9 Hash#select! returns Hash; ISO says nothing.
def select!(&b)
+ return to_enum :select! unless block_given?
+
keys = []
self.each_key{|k|
v = self[k]
- unless b.call(k, v)
+ unless b.call([k, v])
keys.push(k)
end
}
@@ -178,10 +180,12 @@ class Hash
# 1.9 Hash#select returns Hash; ISO says nothing.
def select(&b)
+ return to_enum :select unless block_given?
+
h = {}
self.each_key{|k|
v = self[k]
- if b.call(k, v)
+ if b.call([k, v])
h[k] = v
end
}