Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add some new Enumerable extensions

* Enumerable#drop_last_while
* Enumerable#take_last_while
* Enumerable#several?
  • Loading branch information...
commit 9b5ae764ad89dac6aa67b35a46a1a607d93ea76f 1 parent 8029835
@bbatsov authored
View
3  README.md
@@ -26,7 +26,10 @@ Or install it yourself as:
* [#tail](http://rdoc.info/github/bbatsov/powerpack/Array#tail-instance_method)
* [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)
+ * [#several?](http://rdoc.info/github/bbatsov/powerpack/Enumerable#several?-instance_method)
* [#take_last](http://rdoc.info/github/bbatsov/powerpack/Enumerable#take_last-instance_method)
+ * [#take_last_while](http://rdoc.info/github/bbatsov/powerpack/Enumerable#take_last_while-instance_method)
* [Hash](http://rdoc.info/github/bbatsov/powerpack/Hash)
* [#symbolize_keys](http://rdoc.info/github/bbatsov/powerpack/Hash#symbolize_keys-instance_method)
* [Numeric](http://rdoc.info/github/bbatsov/powerpack/Numeric)
View
3  lib/powerpack/enumerable.rb
@@ -1,2 +1,5 @@
require_relative 'enumerable/drop_last'
+require_relative 'enumerable/drop_last_while'
+require_relative 'enumerable/several'
require_relative 'enumerable/take_last'
+require_relative 'enumerable/take_last_while'
View
21 lib/powerpack/enumerable/drop_last_while.rb
@@ -0,0 +1,21 @@
+unless Enumerable.method_defined? :drop_last_while
+ module Enumerable
+ # Drops the last elements of an enumerable meeting a predicate.
+ #
+ # @return [Array] an array containing the remaining elements
+ #
+ # @example
+ # [1, 2, 3].drop_last_while(&:odd?) #=> [1, 2]
+ def drop_last_while
+ return to_enum(:drop_last_while) unless block_given?
+
+ ary = []
+ dropping = true
+ reverse_each do |obj|
+ ary << obj unless dropping &&= yield(obj)
+ end
+
+ ary.reverse!
+ end
+ end
+end
View
37 lib/powerpack/enumerable/several.rb
@@ -0,0 +1,37 @@
+unless Enumerable.method_defined? :several?
+ module Enumerable
+ # Checks if two or more elements meet a certain predicate.
+ #
+ # @example
+ # [1, 2, 3, 4].several?(&:even?) #=> true
+ # [1, 1, 3, 3].several?(&: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].several? #=> false
+ # [1, 2, 3].several? #=>true
+ def several?
+ found_count = 0
+
+ if block_given?
+ each do |*o|
+ if yield(*o)
+ found_count += 1
+ return true if found_count > 1
+ end
+ end
+ else
+ each do |o|
+ if o
+ found_count += 1
+ return true if found_count > 1
+ end
+ end
+ end
+
+ false
+ end
+ end
+end
View
21 lib/powerpack/enumerable/take_last_while.rb
@@ -0,0 +1,21 @@
+unless Enumerable.method_defined? :take_last_while?
+ module Enumerable
+ # Take the last n elements of an enumerable meeting a certain predicate.
+ #
+ # @return [Array] an array containing the matching elements
+ #
+ # @example
+ # [1, 2, 3, 5].take_last_while(&:odd?) #=> [5, 3]
+ def take_last_while
+ return to_enum(:take_last_while) unless block_given?
+
+ array = []
+ reverse_each do |elem|
+ return array unless yield(elem)
+ array << elem
+ end
+
+ array
+ end
+ end
+end
View
7 spec/powerpack/enumerable/drop_last_while_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe 'Enumerable#drop_last_while' do
+ it 'drops the last elements while a pred is true' do
+ expect([1, 2, 3, 4, 6].drop_last_while(&:even?)).to eq([1, 2, 3])
+ end
+end
View
27 spec/powerpack/enumerable/several_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe 'Enumerable#several' do
+ context 'with block' do
+ it 'returns true if more than 1 element matches the predicate' do
+ expect([1, 2, 3, 4].several?(&:even?)).to be_true
+ end
+
+ it 'returns false if just 1 element matches the predicate' do
+ expect([1, 3, 4].several?(&:even?)).to be_false
+ end
+
+ it 'returns false if no elements match the predicate' do
+ expect([1, 3, 4].several?(&:even?)).to be_false
+ end
+ end
+
+ context 'without block' do
+ it 'returns true if there are 2 or more non nil/false elements' do
+ expect([1, 2, 3, 4].several?).to be_true
+ end
+
+ it 'returns false if there are less than 2 non nil/false elements' do
+ expect([1, nil, false].several?).to be_false
+ end
+ end
+end
View
7 spec/powerpack/enumerable/take_last_while_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe 'Enumerable#take_last_while' do
+ it 'takes the last elements while a pred is true' do
+ expect([1, 2, 3, 4, 6].take_last_while(&:even?)).to eq([6, 4])
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.