- **
- accumulate
- cascade
- collect_if
- collect_with_counter
- collect_with_index
- combinations
- commonality
- compact_collect
- compact_map
- count
- cross
- cross
- each_by
- each_pair
- each_permutation
- each_slice
- elementwise
- entropy
- every
- ew
- filter_collect
- filter_map
- find_collisions
- frequency
- graph
- ideal_entropy
- map_if
- map_with_counter
- map_with_index
- mode
- none?
- nonuniq
- nonuniq!
- occur
- one?
- partition_by
- permutation_number
- permute
- probability
- project
- to_h
- uniq_by
- where
Produces an array of arrays of all possible combinations of the given arrays in the position given. (Explain me better?)
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"]
[ show source ]
# File lib/facets/core/enumerable/self/combinations.rb, line 23 def self.combinations(head, *rest) crest = rest.empty? ? [[]] : combinations(*rest) head.inject([]) { |combs, item| combs + crest.map { |comb| [item] + comb } } end
Provides the cross-product of two or more Enumerables. This is the class-level method. The instance method calls on this.
Enumerable.cross([1,2], [4], ["apple", "banana"]) #=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]] Enumerable.cross([1,2], [3,4]) #=> [[1, 3], [1, 4], [2, 3], [2, 4]]
[ show source ]
# File lib/facets/core/enumerable/self/cross.rb, line 21 def self.cross(*enums, &block) raise if enums.empty? gens = enums.map{|e| Generator.new(e)} return [] if gens.any? {|g| g.end?} sz = gens.size res = [] tuple = Array.new(sz) loop do # fill tuple (0 ... sz).each { |i| tuple[i] = gens[i].current } if block.nil? res << tuple.dup else block.call(tuple.dup) end # step forward gens[-1].next (sz-1).downto(0) do |i| if gens[i].end? if i > 0 gens[i].rewind gens[i-1].next else return res end end end end #loop end
Operator alias for cross-product.
a = [1,2] ** [4,5] a #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
[ show source ]
# File lib/facets/core/enumerable/op_pow.rb, line 11 def **(enum) Enumerable.cross(self, enum) end
Project has_many Group Group has_many User projects.groups.accumulate.users
[ show source ]
# File lib/facets/core/enumerable/accumulate.rb, line 16 def accumulate Functor.new do |op, *args| self.inject([]) { |a, x| a << x.send(op, *args) }.flatten end end
Cascade actions on each enumerated element.
[9, 19, 29].cascade :succ, :to_s, :reverse
> ["01", "02", "03"]
[ show source ]
# File lib/facets/core/enumerable/cascade.rb, line 12 def cascade(*methods) methods.inject(self) { |ary, method| ary.map{ |x| x.send(method)}} end
[ show source ]
# File lib/facets/core/enumerable/collect_if.rb, line 4 def collect_if(&b) a = map(&b) # to get the same semantics as select{|e| e} a.delete(false) a.compact! a end
Alias for collect_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]
[ show source ]
# File lib/facets/core/enumerable/collect_with_index.rb, line 9 def collect_with_index r = [] each_index do |i| r << yield(self[i], i) end r end
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. No guarantee about the order of the elements in the resulting array is made.
Note: The result will be an array if you supply no block and a hash otherwise.
[1, 2, 2, 3, 4, 4].commonality # => { 2 => [2], 4 => [4] } ["foo", "bar", "a"].commonality { |str| str.length } # => { 2 => ["foo, "bar"] } # Returns all persons that share their last name with another person. persons.collisions { |person| person.last_name }
[ show source ]
# File lib/facets/core/enumerable/commonality.rb, line 22 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
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.
[ show source ]
# File lib/facets/core/enumerable/compact_collect.rb, line 17 def compact_collect #:yield: filter_collect do |item| new_item = yield(item) throw(:skip) if new_item.nil? new_item end end
Alias for compact_collect
Count the number of items in an enuerable 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
[ show source ]
# File lib/facets/core/enumerable/count.rb, line 16 def count(*c) self.select{ |*i| i == c }.length end
The instance level cross-product method.
a = [] [1,2].cross([4,5]){|elem| a << elem } a #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
[ show source ]
# File lib/facets/core/enumerable/cross.rb, line 17 def cross(*enums, &block) Enumerable.cross(self, *enums, &block) end
Alias for each_slice
Iterators ovr each element pairing.
[:a,:b,:c,:d].each_pair { |a,b| puts "#{a} -> #{b}" }
produces
a -> b c -> d
[ show source ]
# File lib/facets/core/enumerable/each_pair.rb, line 13 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
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
[ show source ]
# File lib/facets/core/enumerable/permute.rb, line 49 def each_permutation() arr = to_a size = arr.size perm_count = (1...size).inject(0) { |s,x| s + x * x.factorial } weights = Array.new(size-1) {|i| (i+1).factorial } s = weights.size x,i,v,pos = nil 0.upto(perm_count) do |v| out = arr[0..0] arr.each_with_index {|x,i| case i when 0: next when s: out.insert(v / weights[i-1], x) else out.insert(v % weights[i] / weights[i-1], x) end } yield out end end
Iterate through slices. If slicing step is not given, the the arity if the block is used.
x = [] [1,2,3,4].each_slice(2){ |a,b| x << [a,b] } x #=> [ [1,2], [3,4] ] x = [] [1,2,3,4,5,6].each_slice(3){ |a| x << a } x #=> [ [1,2,3], [4,5,6] ]
[ show source ]
# File lib/facets/core/enumerable/each_slice.rb, line 15 def each_slice(step=nil, &yld) if step cnt = step n = length / cnt n += 1 if length % cnt > 0 n.times { |i| yld.call(*self.slice(i*cnt,cnt)) } return cnt else cnt = yld.arity.abs n = length / cnt n += 1 if length % cnt > 0 n.times { |i| yld.call(*self.slice(i*cnt,cnt)) } return cnt end end
Returns an elementwise Functor designed to make R-like elementwise operations possible.
[1,2].ew + 3 #=> [4,5] [1,2].ew + [4,5] #=> [5,7] [1,2].ew + [[4,5],3] #=> [[5,7],[4,5]
[ show source ]
# File lib/facets/core/enumerable/ew.rb, line 16 def elementwise Functor.new do |op,*args| a = args.collect do |arg| if arg.kind_of?(Enumerable) ln = ( arg.length > self.length ? self.length : arg.length ) self[0...ln].zip(arg[0...ln]).collect{ |a,b| a.send(op,b) } #self[0...ln].zip(arg[0...1n]).collect{ |a,b| b ? a.send(op,b) : nil } else self.collect{ |a| a.send(op,arg) } end end a.flatten! if args.length == 1 a end end
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 #=>
[ show source ]
# File lib/facets/core/enumerable/entropy.rb, line 15 def entropy arr = self.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
Returns an elementwise Functor. This allows you to map a method on to every element.
[1,2,3].every + 3 #=> [4,5,6] ['a','b','c'].every.upcase #=> ['A','B','C']
[ show source ]
# File lib/facets/core/enumerable/every.rb, line 13 def every Functor.new do |op,*args| self.collect{ |a| a.send(op,*args) } end end
Alias for elementwise
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.
[ show source ]
# File lib/facets/core/enumerable/filter_collect.rb, line 18 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 for filter_collect
Like commonality but returns an array if no block is given.
[ show source ]
# File lib/facets/core/enumerable/find_collisions.rb, line 7 def find_collisions( &blk ) #:yield: if block_given? commonality( &blk ) else commonality.values.flatten.uniq end end
Generates a hash mapping each unique symbol in the array to the absolute frequency it appears.
[ show source ]
# File lib/facets/core/enumerable/frequency.rb, line 8 def frequency probs = Hash.new(0) each do | e | probs[e] += 1 end probs end
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.graph { |n| [n, n*n] } # { 1=>1, 2=>4, 3=>9 } sq_roots = numbers.graph { |n| [n*n, n] } # { 1=>1, 4=>2, 9=>3 }
[ show source ]
# File lib/facets/core/enumerable/graph.rb, line 22 def graph(&yld) if yld inject({}) do |h,kv| nk, nv = yld[*kv] h[nk] = nv h end else Hash[*self.to_a.flatten] end end
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).
[ show source ]
# File lib/facets/core/enumerable/ideal_entropy.rb, line 13 def ideal_entropy arr = self.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
Alias for collect_if
Alias for collect_with_index
Alias for collect_with_index
In Statistics mode is the value that occurs most frequently in a given set of data.
[ show source ]
# File lib/facets/core/enumerable/mode.rb, line 7 def mode count = Hash.new(0) each {|x| count[x] += 1 } count.sort_by{|k,v|v}.last[0] 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
[ show source ]
# File lib/facets/core/enumerable/none.rb, line 20 def none? # :yield: e if block_given? not self.any? { |e| yield e } else not self.any? end end
[ show source ]
# File lib/facets/core/enumerable/nonuniq.rb, line 7 def nonuniq h1 = {} h2 = {} each {|i| h2[i] = true if h1[i] h1[i] = true } h2.keys end
[ show source ]
# File lib/facets/core/enumerable/nonuniq.rb, line 17 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
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]
[ show source ]
# File lib/facets/core/enumerable/occur.rb, line 17 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
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
[ show source ]
# File lib/facets/core/enumerable/one.rb, line 20 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
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.
[ show source ]
# File lib/facets/core/enumerable/partition_by.rb, line 19 def partition_by #:yield: result = {} self.each do |e| value = yield e (result[value] ||= []) << e end result end
[ show source ]
# File lib/facets/core/enumerable/permute.rb, line 22 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
[ show source ]
# File lib/facets/core/enumerable/permute.rb, line 6 def permute(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
Generates a hash mapping each unique symbol in the array to the relative frequency, i.e. the probablity, of it appearence.
[ show source ]
# File lib/facets/core/enumerable/probability.rb, line 10 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
[ show source ]
# File lib/facets/core/enumerable/project.rb, line 7 def project(&block) self.map{|x| x.instance_eval(&block) } end
Produces a hash from an Enumerable with index for keys.
enu = 'a'..'b' enu.to_h #=> { 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_h{ |e,i| e } #=> { 0=>'a', 1=>'b' }
See also graph.
[ show source ]
# File lib/facets/core/enumerable/to_h.rb, line 18 def to_h( &blk ) h = {} if block_given? each_with_index{ |e,i| h[i] = blk.call(e,i) } else each_with_index{ |e,i| h[i] = e } end h end
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]
[ show source ]
# File lib/facets/core/enumerable/uniq_by.rb, line 12 def uniq_by #:yield: h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x} end
[ show source ]
# File lib/facets/core/enumerable/where.rb, line 7 def where(&block) self.select{|x| x.instance_eval(&block) } end