# TITLE # # Collect # # = DESCRIPTION # # Enumerble collection extensions. # # = AUTHORS # # CREDIT Florian Gross # CREDIT Thomas Sawyer # CREDIT Gavin Sinclair # module Enumerable # Same as #collect but with an iteration counter. # # a = [1,2,3].collect_with_index { |e,i| e*i } # a #=> [0,2,6] # def collect_with_index r = [] each_index do |i| r << yield(self[i], i) end r end alias_method( :map_with_index, :collect_with_index ) # DEPRECATE? # Why the term counter? There may be a change in Ruby 2.0 # to use this word instead of index. Index will # still be used for Array, since that is the proper meaning # in that context. In the mean time, aliases are provided. alias_method( :collect_with_counter, :collect_with_index ) alias_method( :map_with_counter, :collect_with_index ) # More appropriate naming since an enumerable is not # neccesarily "indexed", as is an Array or Hash. alias_method :each_with_counter, :each_with_index # Collects/Maps and filters items out in one single step. # You can use throw(:skip) in the supplied block to indicate that the # current item should not end up in the resulting array. # # # Return names of all person with an age of at least 18. # persons.filter_collect do |person| # throw(:skip) if person.age < 18 # person.name # end # # Also see Enumerable#collect, Enumerable#find_all. # def filter_collect #:yield: result = [] self.each do |item| catch(:skip) do new_item = yield(item) result << new_item end end return result end alias_method :filter_map, :filter_collect # Collects/Maps and compacts items in one single step. # The items for which the supplied block returns +nil+ will not # end up in the resulting array. # # # Return telephone numbers of all persons that have a telephone number. # persons.compact_collect { |person| person.telephone_no } # # Also see Enumerable#collect, Enumerable#map, Array#compact. # def compact_collect #:yield: filter_collect do |item| new_item = yield(item) throw(:skip) if new_item.nil? new_item end end alias_method :compact_map, :compact_collect # Say you want to count letters-- # # some_text.injecting(Hash.new(0) {|h,l| h[l] += 1} # # vs # # some_text.inject(Hash.new(0)) {|h,l| h[l] +=1; h} # #-- # CREDIT Louis J Scoras #++ def injecting(s) inject(s) do |k, i| yield(k, i); k end end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin test require 'test/unit' class TestEnumerableCollect < Test::Unit::TestCase def test_filter_collect e = [3,4] a = [1,2,3,4].filter_collect { |n| throw(:skip) if n < 3 n } assert_equal( e, a ) end def test_compact_collect a = [1,2,nil,4].compact_collect { |e| e } assert_equal( [1,2,4], a ) end def test_filter_collect e = [3,4] a = [1,2,3,4].filter_collect { |n| throw(:skip) if n < 3 n } assert_equal( e, a ) end def test_compact_collect a = [1,2,nil,4].compact_collect { |e| e } assert_equal( [1,2,4], a ) end end =end