#
# == extensions/enumerable.rb
#
# Adds methods to the builtin Enumerable module.
#
require "extensions/_base"
#
# * Enumerable#build_hash
#
ExtensionsProject.implement(Enumerable, :build_hash) do
module Enumerable
#
# Like #map/#collect, but it generates a Hash. The block
# is expected to return two values: the key and the value for the new hash.
# numbers = (1..3)
# squares = numbers.build_hash { |n| [n, n*n] } # 1=>1, 2=>4, 3=>9
# sq_roots = numbers.build_hash { |n| [n*n, n] } # 1=>1, 4=>2, 9=>3
#
def build_hash
result = {}
self.each do |elt|
key, value = yield elt
result[key] = value
end
result
end
end
# There was a bug in Hash which causes the above code to issue a warning when
# used with a Hash. That was fixed on 2003-10-24.
if RUBY_RELEASE_DATE < "2003-10-25"
class Hash #:nodoc:
def build_hash
result = {}
self.each_pair do |k, v|
key, value = yield(k, v)
result[key] = value
end
result
end
end
end
end
#
# Enumerable#mapf
#
ExtensionsProject.implement(Enumerable, :mapf) do
module Enumerable
#
# "map function"
# enum.mapf(:x)
# is short for
# enum.map { |elt| elt.x }
#
def mapf(message)
self.map { |elt| elt.send(message) }
end
end
end
#
# Enumerable#collectf
#
ExtensionsProject.implement(Enumerable, :collectf) do
module Enumerable
alias collectf mapf
end
end
#
# * Enumerable#includes?
#
ExtensionsProject.implement(Enumerable, :includes?) do
module Enumerable
alias includes? include?
end
end
#
# * Enumerable#contains?
#
ExtensionsProject.implement(Enumerable, :contains?) do
module Enumerable
alias contains? include?
end
end
#
# * Enumerable#has?
#
ExtensionsProject.implement(Enumerable, :has?) do
module Enumerable
alias has? include?
end
end
#
# * Enumerable#map_with_index
#
ExtensionsProject.implement(Enumerable, :map_with_index) do
module Enumerable
#
# Same as Enumerable#map, but the index is yielded as well. See
# Enumerable#each_with_index.
# puts files.map_with_index { |fn, idx| "#{idx}. #{fn}" }
# print "Please select a file (0-#{files.size}): "
#
def map_with_index
result = []
self.each_with_index do |elt, idx|
result << yield(elt, idx)
end
result
end
end
end
#
# * Enumerable#collect_with_index
#
ExtensionsProject.implement(Enumerable, :collect_with_index) do
module Enumerable
alias collect_with_index map_with_index
end
end
#
# * Enumerable#partition_by
#
ExtensionsProject.implement(Enumerable, :partition_by) do
module Enumerable
#
# See Enumerable#partition for the background. #partition_by is best
# explained by example.
#
# (1..5).partition_by { |n| n % 3 }
# # -> { 0 => [3], 1 => [1, 4], 2 => [2,5] }
#
# ["I had", 1, "dollar and", 50, "cents"].partition_by { |e| e.class }
# # -> { String => ["I had","dollar and","cents"], Fixnum => [1,50] }
#
# #partition_by is used to group items in a collection by something they
# have in common. The common factor is the key in the resulting hash, the
# array of like elements is the value.
#
def partition_by
result = {}
self.each do |e|
value = yield e
(result[value] ||= []) << e
end
result
end
end
end
#
# * Enumerable#none?
#
ExtensionsProject.implement(Enumerable, :none?) do
module Enumerable
#
# Enumerable#none? is the logical opposite of the builtin method Enumerable#any?. It
# returns +true+ if and only if _none_ of the elements in the collection satisfy the
# predicate.
#
# If no predicate is provided, Enumerable#none? returns +true+ if and only if _none_ of the
# elements have a true value (i.e. not +nil+ or +false+).
#
# [].none? # true
# [nil].none? # true
# [5,8,9].none? # false
# (1...10).none? { |n| n < 0 } # true
# (1...10).none? { |n| n > 0 } # false
#
def none? # :yield: e
if block_given?
not self.any? { |e| yield e }
else
not self.any?
end
end
end
end
#
# * Enumerable#one?
#
ExtensionsProject.implement(Enumerable, :one?) do
module Enumerable
#
# Enumerable#one? returns +true+ if and only if exactly one element in the
# collection satisfies the given predicate.
#
# If no predicate is provided, Enumerable#one? returns +true+ if and only if exactly
# one element has a true value (i.e. not +nil+ or +false+).
#
# [].one? # false
# [nil].one? # false
# [5].one? # true
# [5,8,9].one? # false
# (1...10).one? { |n| n == 5 } # true
# (1...10).one? { |n| n < 5 } # false
#
def one? # :yield: e
matches = 0
if block_given?
self.each do |e|
if yield(e)
matches += 1
return false if matches > 1
end
end
return (matches == 1)
else
one? { |e| e }
end
end
end
end
#
# * Object.in?
# This has special treatment: it's included here and in object.rb, so we don't
# want a warning if it's alredy defined.
#
unless Object.method_defined?(:in?)
ExtensionsProject.implement(Object, :in?) do
class Object
def in?(enumerable) # :nodoc: It's documented in object.rb.
enumerable.include?(self)
end
end
end
end