Module Enumerable
In: lib/core/facets/enumerable/accumulate.rb
lib/core/facets/enumerable/cluster_by.rb
lib/core/facets/enumerable/commonality.rb
lib/core/facets/enumerable/compact_map.rb
lib/core/facets/enumerable/count.rb
lib/core/facets/enumerable/defer.rb
lib/core/facets/enumerable/divide.rb
lib/core/facets/enumerable/duplicates.rb
lib/core/facets/enumerable/each_by.rb
lib/core/facets/enumerable/entropy.rb
lib/core/facets/enumerable/every.rb
lib/core/facets/enumerable/ewise.rb
lib/core/facets/enumerable/filter.rb
lib/core/facets/enumerable/frequency.rb
lib/core/facets/enumerable/group_by.rb
lib/core/facets/enumerable/inject.rb
lib/core/facets/enumerable/map_detect.rb
lib/core/facets/enumerable/map_send.rb
lib/core/facets/enumerable/map_with_index.rb
lib/core/facets/enumerable/mash.rb
lib/core/facets/enumerable/mode.rb
lib/core/facets/enumerable/modulate.rb
lib/core/facets/enumerable/none.rb
lib/core/facets/enumerable/occur.rb
lib/core/facets/enumerable/one.rb
lib/core/facets/enumerable/per.rb
lib/core/facets/enumerable/probability.rb
lib/core/facets/enumerable/split.rb
lib/core/facets/enumerable/sum.rb
lib/core/facets/enumerable/take.rb
lib/core/facets/enumerable/uniq_by.rb
lib/core/facets/to_hash.rb
lib/more/facets/enumargs.rb
lib/more/facets/thread.rb

This is a simple reimplementation of the core Enumerable module to allow the methods to take and pass-on arbitrary arguments to the underlying each call. This library uses Enumerator and scans Enumerable so it can alwasy stay in sync.

NOTE Any Enumerable method with a negative arity cannot do pass arguments due to ambiguity in the argument count. So the methods inject and zip do NOT work this way, but simply work as they do in Enumerable. The method find (and detect) though has been made to work by removing its rarely used optional parameter and providing instead an optional keyword parameter (:ifnone => …). Please keep these difference in mind.

  require 'enumargs'

  class T
    include Enumerable::Arguments
    def initialize(arr)
      @arr = arr
    end
    def each(n)
      arr.each{ |e| yield(e+n) }
    end
  end

  t = T.new([1,2,3])
  t.collect(4)
  #=> [5,6,7]

Methods

Classes and Modules

Module Enumerable::Arguments

Public Instance methods

Accumulate a set of a set.

For example, in an ORM design if Group has_many User then

  groups.accumulate.users

will return a list of users from all groups.

CREDIT: George Moshchovitis

Similar to group_by but returns an array of the groups. Returned elements are sorted by block.

   %w{this is a test}.cluster_by {|x| x[0]}

produces

   [ ['a'], ['is'], ['this', 'test'] ]

CREDIT: Erik Veenstra

collect_with_index()

Alias for map_with_index

Returns all items that are equal in terms of the supplied block. If no block is given objects are considered to be equal if they return the same value for Object#hash and if obj1 == obj2.

  [1, 2, 2, 3, 4, 4].commonality # => { 2 => [2], 4 => [4] }

  ["foo", "bar", "a"].commonality { |str| str.length }
  # => { 3 => ["foo, "bar"] }

  # Returns all persons that share their last name with another person.
  persons.collisions { |person| person.last_name }

CREDIT: Florian Gross

compact_collect(trash=nil, &block)

Alias for compact_map

A more versitle compact method. It can be used to collect and filter items out in one single step.

  [1,2,3].compact_map do |n|
    n < 1 ? nil : n
  end

produces

  [2,3]

NOTE: Perhaps nicer to have as added functionality for compact.

CREDIT: Trans

Count the number of items in an enumerable equal (==) to the given object(s).

  e = [ 'a', '1', 'a' ]
  e.count('1')     #=> 1
  e.count('a')     #=> 2
  e.count('a', 1)  #=> 3

Note that Hash#count only considers values.

  e = { 'a' => 2, 'x' => 2, 'b' => 1 }
  e.count(1) #=> 1
  e.count(2) #=> 2

CREDIT: Trans

Without a block: wrap the Enumerable object in such a way that map, select and similar operations are performed "horizontally" across a series of blocks, instead of building an array of results at each step. This reduces memory usage, allows partial results to be provided early, and permits working with infinite series.

  a = (1..1_000_000_000).defer.select{ |i| i % 2 == 0 }.
                               map{ |i| i + 100 }.
                               take(10).to_a

With a block: the block acts as an arbitrary filter on the data. Unlike map, it can choose to drop elements from the result, and/or add additional ones. The first object passed to the block is the receiver of the output.

  (1..1_000_000_000).
    defer { |out,i| out << i if i % 2 == 0 }.  # like select
    defer { |out,i| out << i + 100 }.          # like map
    take(10).
    each { |i| puts i }

Using with a block, defer(&b), is equivalent to:

  defer.filter(&b)

Use a method like to_a or to_h at the end of the chain when you want an Array or Hash built with the results, or each{…} if you just want to output each result and discard it.

Divide on matching pattern.

  ['a1','b1','a2','b2'].divide(/^a/)
  => [['a1,'b1'],['a2','b2']]

CREDIT: Trans

duplicates()

Alias for nonuniq

Iterate through slices. If slice steps is not given, the arity of the block is used.

  x = []
  [1,2,3,4].each_by{ |a,b| x << [a,b] }
  x  #=> [ [1,2], [3,4] ]

  x = []
  [1,2,3,4,5,6].each_by(3){ |a| x << a }
  x  #=> [ [1,2,3], [4,5,6] ]

This is just like each_slice, except that it will check the arity of the block. If each_slice ever suppots this this method can be deprecated.

CREDIT: Trans

Returns an elementwise Functor designed to make R-like elementwise operations possible.

  [1,2].elementwise + 3          #=> [4,5]
  [1,2].elementwise + [4,5]      #=> [5,7]
  [1,2].elementwise + [[4,5],3]  #=> [[5,7],[4,5]

Shannon‘s entropy for an array - returns the average bits per symbol required to encode the array. Lower values mean less "entropy" - i.e. less unique information in the array.

  %w{ a b c d e e e }.entropy  #=>

CREDIT: Derek

Returns an elemental object. This allows you to map a method on to every element.

  r = [1,2,3].every + 3  #=> [4,5,6]

In place version of every.

ewise(count=1)

Alias for elementwise

The block acts as an arbitrary filter on the data. Unlike map, it can choose to drop elements from the result, and/or add additional ones. The first object passed to the block is the receiver of the output.

  (1..1_000_000_000).
    filter { |out,i| out << i if i % 2 == 0 }.  # like select
    filter { |out,i| out << i + 100 }.          # like map
    take(10).each { |i| puts i }

Generates a hash mapping each unique symbol in the array to the absolute frequency it appears.

CREDIT: Brian Schröder

graph(&yld)

Alias for mash

group_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.

  (1..5).group_by { |n| n % 3 }
       #=> { 0 => [3], 1 => [1, 4], 2 => [2,5] }

  ["I had", 1, "dollar and", 50, "cents"].group_by { |e| e.class }
       #=> { String => ["I had","dollar and","cents"], Fixnum => [1,50] }

CREDIT: Erik Veenstra

Returns the maximum possible Shannon entropy of the array with given size assuming that it is an "order-0" source (each element is selected independently of the next).

CREDIT: Derek

A small variation of Inject that save one from having to return the aggregating or memo argument.

Say you want to count letters.

   some_text.inject!(Hash.new(0)) {|h,l| h[l] += 1}

vs

   some_text.inject(Hash.new(0)) {|h,l| h[l] +=1; h}

CREDIT: David Black, Louis J Scoras

Yield each element to the block. Returns the result of the block when the block is true, terminating early as detect does.

  obj1.foo? #=> false
  obj2.foo? #=> true

  obj2.foo  #=> "a value"

  [obj1, obj2].map_detect { |obj| obj.foo if obj.foo? } #=> "a value"

If the block is never true, return the object given in the first parameter, or nil if none specified.

  [1,2,3].map_detect { |_| false }    #=> nil
  [false].map_detect(1) { |_| false } #=> 1

Send a message to each element and collect the result.

CREDIT: Sean O‘Halpin

Same as collect but with an iteration counter.

  a = [1,2,3].collect_with_index { |e,i| e*i }
  a  #=> [0,2,6]

CREDIT: Gavin Sinclair

Like map/collect, but 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.mash { |n| [n, n*n] }   # { 1=>1, 2=>4, 3=>9 }
  sq_roots = numbers.mash { |n| [n*n, n] }   # { 1=>1, 4=>2, 9=>3 }

The name "mash" stands for "map hash".

CREDIT: Andrew Dudzik (adudzik), Trans

In Statistics mode is the value that occurs most frequently in a given set of data.

CREDIT: Robert Klemme

Modulate. Divide an array into groups by modulo of the index.

[2,4,6,8].modulate(2) #=> [[2,6],[4,8]]

CREDIT: Trans

NOTE: Would the better name for this be ‘collate’?

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: Gavin Sinclair

Returns a list on non-unique,

  [1,1,2,2,3,4,5].nonuniq  #=> [1,2]

CREDIT: Martin DeMello

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]

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: Gavin Sinclair

Per element meta-functor.

  [1,2,3].per + 3             #=> [4,5,6]
  [1,2,3].per(:map) + 3       #=> [4,5,6]
  [1,2,3].per(:select) > 1    #=> [2,3]

  [1,2,3].per.map + 3       #=> [4,5,6]
  [1,2,3].per.select > 1    #=> [2,3]

Generates a hash mapping each unique element in the array to the relative frequency, i.e. the probablity, of it appearence.

CREDIT: Brian Schröder

Split on matching pattern. Unlike divide this does not include matching elements.

  ['a1','a2','b1','a3','b2','a4'].split(/^b/)
  => [['a1','a2'],['a3'],['a4']]

CREDIT: Trans

Uses #+ to sum the enumerated elements.

  [1,2,3].sum  #=> 6
  [3,3,3].sum  #=> 9

Return the first n items from the collection

Like Enumerable#map but each iteration is processed via a separate thread.

CREDIT Sean O‘Halpin

Like Enumerable#map_send but each iteration is processed via a separate thread.

CREDIT Sean O‘Halpin

Convert an Enumerable object into a hash by first turning it into an array.

CREDIT: Trans

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]

[Validate]