Permalink
Browse files

Add Enumerable#exactly?

  • Loading branch information...
1 parent b64cce0 commit 29230704ae802db95d1f710ed9baadfb9101fe3c @bbatsov committed Sep 4, 2013
Showing with 67 additions and 0 deletions.
  1. +1 −0 README.md
  2. +1 −0 lib/powerpack/enumerable.rb
  3. +38 −0 lib/powerpack/enumerable/exactly.rb
  4. +27 −0 spec/powerpack/enumerable/exactly_spec.rb
View
@@ -27,6 +27,7 @@ Or install it yourself as:
* [Enumerable](http://rdoc.info/github/bbatsov/powerpack/Enumerable)
* [#drop_last](http://rdoc.info/github/bbatsov/powerpack/Enumerable#drop_last-instance_method)
* [#drop_last_while](http://rdoc.info/github/bbatsov/powerpack/Enumerable#drop_last_while-instance_method)
+ * [#exactly?](http://rdoc.info/github/bbatsov/powerpack/Enumerable#exactly?-instance_method)
* [#frequencies](http://rdoc.info/github/bbatsov/powerpack/Enumerable#frequencies-instance_method)
* [#several?](http://rdoc.info/github/bbatsov/powerpack/Enumerable#several?-instance_method)
* [#sum](http://rdoc.info/github/bbatsov/powerpack/Enumerable#sum-instance_method)
@@ -1,5 +1,6 @@
require_relative 'enumerable/drop_last'
require_relative 'enumerable/drop_last_while'
+require_relative 'enumerable/exactly'
require_relative 'enumerable/frequencies'
require_relative 'enumerable/several'
require_relative 'enumerable/sum'
@@ -0,0 +1,38 @@
+unless Enumerable.method_defined? :exactly?
+ module Enumerable
+ # Checks if exactly n elements meet a certain predicate.
+ #
+ # @param n [Fixnum] the number of matches required
+ # @return [Boolean] true if we get exactly n matches, false otherwise
+ #
+ # @example
+ # [1, 2, 3, 4].exactly?(2, &:even?) #=> true
+ # [1, 1, 3, 3].exactly?(2, &:even?) #=> false
+ #
+ # Without a block uses the identify of the elements as default predicate.
+ # This means that nil and false elements will be ignored.
+ #
+ # @example
+ # [1, false, nil].exactly? #=> false
+ # [1, 2, 3].exactly?(3) #=>true
+ def exactly?(n)
+ found_count = 0
+
+ if block_given?
+ each do |*o|
+ if yield(*o)
+ found_count += 1
+ end
+ end
+ else
+ each do |o|
+ if o
+ found_count += 1
+ end
+ end
+ end
+
+ n == found_count
+ end
+ end
+end
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe 'Enumerable#exactly' do
+ context 'with block' do
+ it 'returns true for exact number of matches' do
+ expect([1, 2, 3, 4].exactly?(2, &:even?)).to be_true
+ end
+
+ it 'returns false for less matches' do
+ expect([1, 3, 4].exactly?(2, &:even?)).to be_false
+ end
+
+ it 'returns false for more matches' do
+ expect([1, 3, 4, 6, 8].exactly?(2, &:even?)).to be_false
+ end
+ end
+
+ context 'without block' do
+ it 'returns true for exact number of non nil/false elements' do
+ expect([1, 2, 3, 4].exactly?(4)).to be_true
+ end
+
+ it 'returns false if there are less non nil/false elements' do
+ expect([1, nil, false].exactly?(4)).to be_false
+ end
+ end
+end

0 comments on commit 2923070

Please sign in to comment.