# TITLE: # # Enumerable Counting # # SUMMARY: # # Extensions related to counting and uniquness. # # AUTHORS: # # - Florian Gross # - Thomas Sawyer # - Gavin Sinclair # - Gavin Kistner # module Enumerable # Count the number of items in an enumerable # equal (==) to the given object. # # e = [ 'a', '1', 'a' ] # e.count('1') #=> 1 # e.count('a') #=> 2 # # Count can also handle multiple-valued blocks. # # e = { 'a' => 2, 'a' => 2, 'b' => 1 } # e.count('a',2) #=> 1 # def count(*c) self.select{ |*i| i == c }.length end # Returns an array of elements for the elements that occur n times. # Or according to the results of a given block. # # [1,1,2,3,3,4,5,5].occur(1) #=> [2,4] # [1,1,2,3,3,4,5,5].occur(2) #=> [1,3,5] # [1,1,2,3,3,4,5,5].occur(3) #=> [] # # [1,2,2,3,3,3].occur(1..1) #=> [1] # [1,2,2,3,3,3].occur(2..3) #=> [2,3] # # [1,1,2,3,3,4,5,5].occur { |n| n == 1 } #=> [2,4] # [1,1,2,3,3,4,5,5].occur { |n| n > 1 } #=> [1,3,5] # def occur(n=nil) #:yield: result = Hash.new { |hash, key| hash[key] = Array.new } self.each do |item| key = item result[key] << item end if block_given? result.reject! { |key, values| ! yield(values.size) } else raise ArgumentError unless n if Range === n result.reject! { |key, values| ! n.include?(values.size) } else result.reject! { |key, values| values.size != n } end end return result.values.flatten.uniq end # CREDIT Gavin Kistner # Uses #+ to sum the enumerated elements. # # [1,2,3].sum #=> 6 # [3,3,3].sum #=> 9 def sum v = 0 each{ |n| v+=n } v end # CREDIT Martin DeMello # def nonuniq h1 = {} h2 = {} each {|i| h2[i] = true if h1[i] h1[i] = true } h2.keys end # # # def nonuniq! # raise unless respond_to?(:replace) # h1 = {} # h2 = {} # each {|i| # h2[i] = true if h1[i] # h1[i] = true # } # self.replace(h2.keys) # end # Return list of dulicate elements. alias_method :duplicates, :nonuniq # Like #uniq, but determines uniqueness based on a given block. # # (-5..5).to_a.uniq_by {|i| i*i } # # produces # # [-5, -4, -3, -2, -1, 0] # def uniq_by #:yield: h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x} end # 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 # #-- # Credit goes to Gavin Sinclair. #++ 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 # 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 # #-- # Credit goes to Gavin Sinclair. #++ def none? # :yield: e if block_given? not self.any? { |e| yield e } else not self.any? end end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin test require 'test/unit' class TestEnumerableCount < Test::Unit::TestCase def test_occur arr = [:a,:b,:a] assert_equal( [:b], arr.occur(1) ) assert_equal( [:a], arr.occur(2) ) assert_equal( [:b], arr.occur(1..1) ) assert_equal( [:a], arr.occur{ |n| n % 2 == 0 } ) end def test_count_01 e = [ 'a', '1', 'a' ] assert_equal( 1, e.count('1') ) assert_equal( 2, e.count('a') ) end def test_count_02 e = [ ['a',2], ['a',2], ['a',2], ['b',1] ] assert_equal( 3, e.count(['a',2]) ) end def test_count_03 e = { 'a' => 2, 'a' => 2, 'b' => 1 } assert_equal( 1, e.count('a',2) ) end def test_uniq_by a = [-5, -4, -3, -2, -1, 0] r = (-5..5).to_a.uniq_by{|i| i*i } assert_equal( a, r ) end def test_one? a = [nil, true] assert( a.one? ) a = [true, false] assert( a.one? ) a = [true, true] assert( ! a.one? ) a = [true, 1] assert( ! a.one? ) a = [1, 1] assert( ! a.one? ) end def test_none? a = [nil, nil] assert( a.none? ) a = [false, false] assert( a.none? ) a = [true, false] assert( ! a.none? ) a = [nil, 1] assert( ! a.none? ) end end =end