Module: Enumerable

Included in:
Archive::Tar::Minitar::Input, Dictionary, Duration, LinkedList, Tuple
Defined in:
lib/more/facets/thread.rb,
lib/more/facets/elementor.rb,
lib/core/facets/conversion.rb,
lib/core/facets/enumerable/each.rb,
lib/core/facets/enumerable/mash.rb,
lib/core/facets/enumerable/count.rb,
lib/core/facets/enumerable/split.rb,
lib/core/facets/enumerable/collect.rb,
lib/core/facets/enumerable/cartesian.rb,
lib/core/facets/enumerable/combination.rb,
lib/core/facets/enumerable/permutation.rb,
lib/core/facets/enumerable/probability.rb

Defined Under Namespace

Classes: Elementor, Enumerator

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cartObject

Provides the cross-product of two or more Enumerables. This is the class-level method. The instance method calls on this.

Enumerable.cart([1,2], [4], ["apple", "banana"])
#=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]

Enumerable.cart([1,2], [3,4])
#=> [[1, 3], [1, 4], [2, 3], [2, 4]]

CREDIT: Thomas Hafner


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/core/facets/enumerable/cartesian.rb', line 34

def self.cartesian_product(*enums, &block)
  result = [[]]
  while [] != enums
    t, result = result, []
    b, *enums = enums
    t.each do |a|
      b.each do |n|
        result << a + [n]
      end
    end
  end
  if block_given?
    result.each{ |e| block.call(e) }
  else
    result
  end
end

.cartesian_product(*enums, &block) ⇒ Object

Provides the cross-product of two or more Enumerables. This is the class-level method. The instance method calls on this.

Enumerable.cart([1,2], [4], ["apple", "banana"])
#=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]

Enumerable.cart([1,2], [3,4])
#=> [[1, 3], [1, 4], [2, 3], [2, 4]]

CREDIT: Thomas Hafner


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/core/facets/enumerable/cartesian.rb', line 15

def self.cartesian_product(*enums, &block)
  result = [[]]
  while [] != enums
    t, result = result, []
    b, *enums = enums
    t.each do |a|
      b.each do |n|
        result << a + [n]
      end
    end
  end
  if block_given?
    result.each{ |e| block.call(e) }
  else
    result
  end
end

.combinations(head, *rest) ⇒ Object

Produces an array of arrays of all possible combinations of the given arrays in the positions given. (Imagine it like a slot machine dial. This gives every combination that could come up.)

a = %w|a b|
b = %w|a x|
c = %w|x y|
Array.combinations(a, b, c).each { |x| p x }

produces

["a", "a", "x"]
["a", "a", "y"]
["a", "x", "x"]
["a", "x", "y"]
["b", "a", "x"]
["b", "a", "y"]
["b", "x", "x"]
["b", "x", "y"]

CREDIT: Florian Gross


28
29
30
31
32
33
# File 'lib/core/facets/enumerable/combination.rb', line 28

def self.combinations(head, *rest)
  crest = rest.empty? ? [[]] : combinations(*rest)
  head.inject([]) { |combs, item|
    combs + crest.map { |comb| [item] + comb }
  }
end

Instance Method Details

#**(enum) ⇒ Object

Operator alias for cross-product.

a = [1,2] ** [4,5]
a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]

CREDIT: Trans


58
59
60
# File 'lib/core/facets/enumerable/cartesian.rb', line 58

def **(enum)
  Enumerable.cartesian_product(self, enum)
end

#accumulateObject

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.



58
59
60
61
62
# File 'lib/more/facets/elementor.rb', line 58

def accumulate
  @_accumulate ||= Functor.new do |op, *args|
    inject([]) { |a, x| a << x.send(op, *args) }.flatten
  end
end

#cartesian_product(*enums, &block) ⇒ Object Also known as: cart

The instance level version of Enumerable::cartesian_product.

a = []
[1,2].cart([4,5]){|elem| a << elem }
a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]

CREDIT: Thomas Hafner


45
46
47
# File 'lib/core/facets/enumerable/cartesian.rb', line 45

def cartesian_product(*enums, &block)
  Enumerable.cartesian_product(self, *enums, &block)
end

#cluster_by(&b) ⇒ Object

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



78
79
80
# File 'lib/core/facets/enumerable/split.rb', line 78

def cluster_by(&b)
  group_by(&b).sort.transpose.pop || []   # group_by(&b).values ?
end

#collect_if(&b) ⇒ Object Also known as: map_if

Conditional collect.

[1,2,3].collect_if { |e| e > 1 }

CREDIT: ? Mauricio Fernandez


80
81
82
83
84
85
86
# File 'lib/core/facets/enumerable/collect.rb', line 80

def collect_if(&b)
  a = map(&b)
  # to get the same semantics as select{|e| e}
  a.delete(false)
  a.compact!
  a
end

#collect_with_indexObject Also known as: map_with_index

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


10
11
12
13
14
15
16
# File 'lib/core/facets/enumerable/collect.rb', line 10

def collect_with_index
  r = []
  each_index do |i|
    r << yield(self[i], i)
  end
  r
end

#combosObject

As with each_combo but returns combos collected in an array.

CREDIT: Trans


101
102
103
104
105
# File 'lib/core/facets/enumerable/cartesian.rb', line 101

def combos
  a = []
  each_combo{ |c| a << c }
  a
end

#commonality(&block) ⇒ Object

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


105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/core/facets/enumerable/probability.rb', line 105

def commonality( &block )
  had_no_block = !block
  block ||= lambda { |item| item }
  result = Hash.new { |hash, key| hash[key] = Array.new }
  self.each do |item|
    key = block.call(item)
    result[key] << item
  end
  result.reject! do |key, values|
    values.size <= 1
  end
  #return had_no_block ? result.values.flatten : result
  return result
end

#compact_collectObject Also known as: compact_map

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.

CREDIT: Florian Gross


62
63
64
65
66
67
68
# File 'lib/core/facets/enumerable/collect.rb', line 62

def compact_collect #:yield:
  filter_collect do |item|
    new_item = yield(item)
    throw(:skip) if new_item.nil?
    new_item
  end
end

#count(*c) ⇒ Object

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

CREDIT: Trans


19
20
21
# File 'lib/core/facets/enumerable/count.rb', line 19

def count(*c)
  self.select{ |*i| i == c }.length
end

#divide(pattern) ⇒ Object

Divide on matching pattern.

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

CREDIT: Trans


58
59
60
61
62
63
64
65
# File 'lib/core/facets/enumerable/split.rb', line 58

def divide(pattern)
  memo = []
  each do |obj|
    memo.push [] if pattern === obj
    memo.last << obj
  end
  memo
end

#each_by(step = nil, &yld) ⇒ Object

Iterate through slices. If slicing step is not given, the the arity if 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] ]

CREDIT: Trans


23
24
25
26
27
28
29
30
# File 'lib/core/facets/enumerable/each.rb', line 23

def each_by(step=nil, &yld)
  if step
    each_slice(step,&yld)
  else
    step = yld.arity.abs
    each_slice(step,&yld)
  end
end

#each_combination(k = 2) ⇒ Object

Yields the block to each unique combination of n elements.

a = %w|a b c d|
a.each_combination(3) do |c|
  p c
end

produces

["a", "b", "c"]
["a", "b", "d"]
["a", "c", "d"]
["b", "c", "d"]

CREDIT: Florian Gross


51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/core/facets/enumerable/combination.rb', line 51

def each_combination(k=2)
  s = to_a
  n = s.size
  return unless (1..n) === k
  idx = (0...k).to_a
  loop do
    yield s.values_at(*idx)
    i = k - 1
    i -= 1 while idx[i] == n - k + i
    break if i < 0
    idx[i] += 1
    (i + 1 ... k).each {|j| idx[j] = idx[i] + j - i}
  end
end

#each_comboObject

Expected to be an enumeration of arrays. This method iterates through combinations of each in position.

a = [ [0,1], [2,3] ]
a.each_combo { |c| p c }

produces

[0, 2]
[0, 3]
[1, 2]
[1, 3]

CREDIT: Trans


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/core/facets/enumerable/cartesian.rb', line 77

def each_combo
  a = collect{ |x|
    x.respond_to?(:to_a) ? x.to_a : 0..x
  }

  if a.size == 1
    r = a.shift
    r.each{ |n|
      yield n
    }
  else
    r = a.shift
    r.each{ |n|
      a.each_combo{ |s|
        yield [n, *s]
      }
    }
  end
end

#each_pairObject

Iterators over each element pairing.

[:a,:b,:c,:d].each_pair { |a,b|  puts "#{a} -> #{b}" }

produces

a -> b
c -> d

CREDIT: Martin DeMello


43
44
45
46
47
48
49
50
51
52
53
# File 'lib/core/facets/enumerable/each.rb', line 43

def each_pair #:yield:
  e1 = nil
  each_with_index do |e,i|
    if i % 2 == 0
      e1 = e
      next
    else
      yield(e1,e)
    end
  end
end

#each_permutationObject

Applys a block to each possible permutation of an array/enumerable.

%w[a b c].each_permutation { |x| puts(x.join('')) }

produces

abc
acb
bac
bca
cab
cba

CREDIT: Daniel Sheppard


63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/core/facets/enumerable/permutation.rb', line 63

def each_permutation()
    pos = Array.new(size) {|i| i}
    s = (0...size).to_a.reverse
    out = nil
    while true
        out = []
        pos.each_with_index {|p,i| out.insert(p, self[i]) }
        yield out
        break if s.each do |i|
            break if pos[i] > 0 && pos[i] -= 1
            pos[i] = i
        end
    end
end

#eachn(&block) ⇒ Object

Collect each n items based on arity.

[1,2,3,4].eachn do |x, y|
  [x,y]
end

produces

[1,2]
[3,4]

CREDIT: Martin DeMello


68
69
70
71
# File 'lib/core/facets/enumerable/each.rb', line 68

def eachn(&block)
  n = block.arity.abs
  each_slice(n) {|i| block.call(*i)}
end

#elementwise(count = 1) ⇒ Object Also known as: ewise

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]

– Special thanks to Martin DeMello for helping to develop this. ++



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/more/facets/elementor.rb', line 128

def elementwise(count=1)
  @_elementwise_functor ||= []
  @_elementwise_functor[count] ||= Functor.new do |op,*args|
    if args.empty?
      r = self
      count.times do
        r = r.collect{ |a| a.send(op) }
      end
      r
    else
      r = args.collect do |arg|
        if Array === arg #arg.kind_of?(Enumerable)
          x = self
          count.times do
            ln = (arg.length > length ? length : arg.length )
            x = x.slice(0...ln).zip(arg[0...ln]).collect{ |a,b| a.send(op,b) }
            #slice(0...ln).zip(arg[0...1n]).collect{ |a,b| b ? a.send(op,b) : nil }
          end
          x
        else
          x = self
          count.times do
            x = x.collect{ |a| a.send(op,arg) }
          end
          x
        end
      end
      r.flatten! if args.length == 1
      r
    end
  end
end

#entropyObject

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


55
56
57
58
59
60
61
62
63
# File 'lib/core/facets/enumerable/probability.rb', line 55

def entropy
  arr = to_a
  probHash = arr.probability
  # h is the Shannon entropy of the array
  h = -1.to_f * probHash.keys.inject(0.to_f) do |sum, i|
    sum + (probHash[i] * (Math.log(probHash[i])/Math.log(2.to_f)))
  end
  h
end

#everyObject Also known as: x, elements

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

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


75
76
77
# File 'lib/more/facets/elementor.rb', line 75

def every
  @_every ||= to_elem
end

#every!Object Also known as: x!, elements!

In place version of #every.

Raises:

  • (NoMethodError)


81
82
83
84
# File 'lib/more/facets/elementor.rb', line 81

def every!
  raise NoMethodError unless respond_to?(:map!)
  @_every_inplace ||= to_elem(:map!)
end

#filter_collectObject Also known as: filter_map

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.

CREDIT: Florian Gross


36
37
38
39
40
41
42
43
44
45
# File 'lib/core/facets/enumerable/collect.rb', line 36

def filter_collect #:yield:
  result = []
  self.each do |item|
    catch(:skip) do
      new_item = yield(item)
      result << new_item
    end
  end
  return result
end

#frequencyObject

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

CREDIT: Brian Schröder


82
83
84
85
86
87
88
89
# File 'lib/core/facets/enumerable/probability.rb', line 82

def frequency
  #probs = Hash.new(0)
  #each do |e|
  #  probs[e] += 1
  #end
  #probs
  inject(Hash.new(0)){|h,v| h[v]+=1; h}
end

#group_byObject Also known as: partition_by

#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

TODO:

- Deprecate #group_by when released for Ruby 1.9.


19
20
21
22
23
24
# File 'lib/core/facets/enumerable/split.rb', line 19

def group_by #:yield:
  #h = k = e = nil
  r = Hash.new
  each{ |e| (r[yield(e)] ||= []) << e }
  r
end

#ideal_entropyObject

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


71
72
73
74
75
# File 'lib/core/facets/enumerable/probability.rb', line 71

def ideal_entropy
  arr = to_a
  unitProb = 1.0.to_f / arr.size.to_f
  (-1.to_f * arr.size.to_f * unitProb * Math.log(unitProb)/Math.log(2.to_f))
end

#inject!(s) ⇒ Object

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


125
126
127
128
129
# File 'lib/core/facets/enumerable/collect.rb', line 125

def inject!(s)
  k = s
  each { |i| yield(k, i) }
  k
end

#injecting(s) ⇒ Object

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}

This may be deprecated in favor of inject!. We make both available for now to make sure (via the test of time) that they are 100% equivalent.

CREDIT: Louis J Scoras


145
146
147
148
149
# File 'lib/core/facets/enumerable/collect.rb', line 145

def injecting(s)
  inject(s) do |k, i|
    yield(k, i); k
  end
end

#map_send(meth, *args) ⇒ Object

Send a message to each element and collect the result.

CREDIT: Sean O'Halpin


96
97
98
99
100
101
102
# File 'lib/core/facets/enumerable/collect.rb', line 96

def map_send(meth, *args) #:yield:
  if block_given?
    map{|e| yield(e.send(meth, *args))}
  else
    map{|e| e.send(meth, *args)}
  end
end

#mash(&yld) ⇒ Object Also known as: graph, collate

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 }

CREDIT: Trans CREDIT: Andrew Dudzik (adudzik)

NOTE: Would #correlate would be better?



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/core/facets/enumerable/mash.rb', line 17

def mash(&yld)
  if yld
    inject({}) do |h, *kv| # Used to be inject({}) do |h,kv|
      r = *yld[*kv]        # The *-op works differnt from to_a on single element hash!!!
      nk, nv = *r          # Used to be nk, nv = *yld[*kv].to_a.flatten
      h[nk] = nv
      h
    end
  else
    Enumerator.new(self,:graph)  # Used to be Hash[*self.to_a] or Hash[*self.to_a.flatten]
  end
end

#modeObject

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

CREDIT: Trans


8
9
10
11
12
# File 'lib/core/facets/enumerable/probability.rb', line 8

def mode
  count = Hash.new(0)
  each {|x| count[x] += 1 }
  count.sort_by{|k,v| v}.last[0]
end

#modulate(modulo) ⇒ Object

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

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

CREDIT: Trans

NOTE: Would this be better named ‘collate’?

Raises:

  • (ArgumentError)


90
91
92
93
94
95
96
97
98
# File 'lib/core/facets/enumerable/split.rb', line 90

def modulate(modulo)
  return to_a if modulo == 1
  raise ArgumentError, 'bad modulo' if size % modulo != 0
  r = Array.new(modulo, [])
  (0...size).each do |i|
    r[i % level] += [self[i]]
  end
  r
end

#none?Boolean

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:

  • (Boolean)


70
71
72
73
74
75
76
# File 'lib/core/facets/enumerable/count.rb', line 70

def none?  # :yield: e
  if block_given?
    not self.any? { |e| yield e }
  else
    not self.any?
  end
end

#nonuniqObject Also known as: duplicates

Returns a list on non-unique,

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

CREDIT: Martin DeMello


133
134
135
136
137
138
139
140
141
# File 'lib/core/facets/enumerable/count.rb', line 133

def nonuniq
  h1 = {}
  h2 = {}
  each {|i|
    h2[i] = true if h1[i]
    h1[i] = true
  }
  h2.keys
end

#occur(n = nil) ⇒ Object

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]

CREDIT: ?


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/core/facets/enumerable/count.rb', line 95

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

#one?Boolean

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

Returns:

  • (Boolean)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/core/facets/enumerable/count.rb', line 39

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

#permutation(number) ⇒ Object Also known as: permute

Permutation proves the possible orders of an enumerable. Each is index by a permutation number. The maximum number of arrangements is the factorial of the size of the array.

CREDIT: Florian Gross


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/core/facets/enumerable/permutation.rb', line 11

def permutation(number)
    arr = to_a
    out = arr[0..0]
    nextfactor = factor = 1
    arr.each_with_index {|x,i|
        case i
        when 0
          next
        else
            nextfactor = factor * (i+1)
            out.insert(number % nextfactor / factor, x)
            factor = nextfactor
        end
    }
    out
end

#permutation_number(original_array = self.to_a.sort) ⇒ Object

Calculate permutation number.

CREDIT: Florian Gross


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/core/facets/enumerable/permutation.rb', line 34

def permutation_number(original_array=self.to_a.sort)
    arr = to_a
    m = 1
    v = 0
    last_indicies = Hash.new(0)
    original_array.each_with_index {|x,i|
        next if i==0
        m *= i
        done = original_array[0..i]
        v += m * arr.select {|y| done.include?(y)}.rindex(x)
    }
    v
end

#probabilityObject

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

CREDIT: Brian Schröder


20
21
22
23
24
25
26
27
28
29
# File 'lib/core/facets/enumerable/probability.rb', line 20

def probability
  probs = Hash.new(0.0)
  size = 0.0
  each do | e |
    probs[e] += 1.0
    size += 1.0
  end
  probs.keys.each{ |e| probs[e] /= size }
  probs
end

#split(pattern) ⇒ Object

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



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/core/facets/enumerable/split.rb', line 39

def split(pattern)
  memo = []
  each do |obj|
    if pattern === obj
      memo.push []
    else
      memo.last << obj
    end
  end
  memo
end

#sumObject

Uses #+ to sum the enumerated elements.

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

CREDIT: Gavin Kistner


121
122
123
124
125
# File 'lib/core/facets/enumerable/count.rb', line 121

def sum
  v = 0
  each{ |n| v+=n }
  v
end

#threaded_mapObject

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

CREDIT Sean O’Halpin



38
39
40
# File 'lib/more/facets/thread.rb', line 38

def threaded_map #:yield:
  map{|e| Thread.new(e){|t| yield t}}.map_send(:value)
end

#threaded_map_send(meth, *args) ⇒ Object

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

CREDIT Sean O’Halpin



47
48
49
50
51
52
53
# File 'lib/more/facets/thread.rb', line 47

def threaded_map_send(meth, *args) #:yield:
  if block_given?
    map{|e| Thread.new(e){|t| yield t.send(meth, *args)}}.map_send(:value)
  else
    map{|e| Thread.new(e){|t| t.send(meth, *args)}}.map_send(:value)
  end
end

#to_elem(meth = nil) ⇒ Object

Create Elementor.



66
67
68
# File 'lib/more/facets/elementor.rb', line 66

def to_elem(meth=nil)
  Elementor.new(self, meth || :map)
end

#to_h(arrayed = nil) ⇒ Object

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

CREDIT: Trans


129
130
131
# File 'lib/core/facets/conversion.rb', line 129

def to_h(arrayed=nil)
  to_a.to_h(arrayed)
end

#to_hash(&blk) ⇒ Object

Produces a hash from an Enumerable with index for keys.

enu = 'a'..'b'
enu.to_hash  #=> { 0=>'a', 1=>'b' }

If a block is passed, the hash values will be set by calling the block with the enumerated element and it’s counter.

enu = 'a'..'b'
enu.to_hash{ |e,i| e }  #=> { 0=>'a', 1=>'b' }

See also #mash.

CREDIT: Trans


114
115
116
117
118
119
120
121
122
# File 'lib/core/facets/conversion.rb', line 114

def to_hash( &blk )
  h = {}
  if blk
    each_with_index{ |e,i| h[i] = blk.call(e,i) }
  else
    each_with_index{ |e,i| h[i] = e }
  end
  h
end

#uniq_byObject

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]

CREDIT: ?


171
172
173
# File 'lib/core/facets/enumerable/count.rb', line 171

def uniq_by #:yield:
  h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x}
end