##
# Enumerable
#
module Enumerable
##
# call-seq:
# enum.drop(n) -> array
#
# Drops first n elements from enum, and returns rest elements
# in an array.
#
# a = [1, 2, 3, 4, 5, 0]
# a.drop(3) #=> [4, 5, 0]
def drop(n)
raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
raise ArgumentError, "attempt to drop negative size" if n < 0
ary = []
self.each {|e| n == 0 ? ary << e : n -= 1 }
ary
end
##
# call-seq:
# enum.drop_while {|arr| block } -> array
#
# Drops elements up to, but not including, the first element for
# which the block returns +nil+ or +false+ and returns an array
# containing the remaining elements.
#
# a = [1, 2, 3, 4, 5, 0]
# a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
def drop_while(&block)
ary, state = [], false
self.each do |e|
state = true if !state and !block.call(e)
ary << e if state
end
ary
end
##
# call-seq:
# enum.take(n) -> array
#
# Returns first n elements from enum.
#
# a = [1, 2, 3, 4, 5, 0]
# a.take(3) #=> [1, 2, 3]
def take(n)
raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
raise ArgumentError, "attempt to take negative size" if n < 0
ary = []
self.each do |e|
break if ary.size >= n
ary << e
end
ary
end
##
# call-seq:
# enum.take_while {|arr| block } -> array
#
# Passes elements to the block until the block returns +nil+ or +false+,
# then stops iterating and returns an array of all prior elements.
#
#
# a = [1, 2, 3, 4, 5, 0]
# a.take_while {|i| i < 3 } #=> [1, 2]
def take_while(&block)
ary = []
self.each do |e|
return ary unless block.call(e)
ary << e
end
ary
end
##
# call-seq:
# enum.each_cons(n) {...} -> nil
#
# Iterates the given block for each array of consecutive
# elements.
#
# e.g.:
# (1..10).each_cons(3) {|a| p a}
# # outputs below
# [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]
# [4, 5, 6]
# [5, 6, 7]
# [6, 7, 8]
# [7, 8, 9]
# [8, 9, 10]
def each_cons(n, &block)
raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
raise ArgumentError, "invalid size" if n <= 0
ary = []
self.each do |e|
ary.shift if ary.size == n
ary << e
block.call(ary.dup) if ary.size == n
end
end
##
# call-seq:
# enum.each_slice(n) {...} -> nil
#
# Iterates the given block for each slice of elements.
#
# e.g.:
# (1..10).each_slice(3) {|a| p a}
# # outputs below
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
def each_slice(n, &block)
raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
raise ArgumentError, "invalid slice size" if n <= 0
ary = []
self.each do |e|
ary << e
if ary.size == n
block.call(ary)
ary = []
end
end
block.call(ary) unless ary.empty?
end
##
# call-seq:
# enum.group_by {| obj | block } -> a_hash
#
# Returns a hash, which keys are evaluated result from the
# block, and values are arrays of elements in enum
# corresponding to the key.
#
# (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
def group_by(&block)
h = {}
self.each do |e|
key = block.call(e)
h.key?(key) ? (h[key] << e) : (h[key] = [e])
end
h
end
##
# call-seq:
# enum.sort_by { |obj| block } -> array
#
# Sorts enum using a set of keys generated by mapping the
# values in enum through the given block.
def sort_by(&block)
ary = []
orig = []
self.each_with_index{|e, i|
orig.push(e)
ary.push([block.call(e), i])
}
if ary.size > 1
__sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
a <=> b
end
end
ary.collect{|e,i| orig[i]}
end
NONE = Object.new
##
# call-seq:
# enum.first -> obj or nil
# enum.first(n) -> an_array
#
# Returns the first element, or the first +n+ elements, of the enumerable.
# If the enumerable is empty, the first form returns nil, and the
# second form returns an empty array.
def first(n=NONE)
if n == NONE
self.each do |e|
return e
end
return nil
else
a = []
i = 0
self.each do |e|
break if n<=i
a.push e
i += 1
end
a
end
end
def count(v=nil, &block)
count = 0
if block
self.each do |e|
count += 1 if block.call(e)
end
else
if v == nil
self.each { count += 1 }
else
self.each do |e|
count += 1 if e == v
end
end
end
count
end
end