class Array
class NilClass
# Provide platform dependent null path. # # @standard # require 'facets/pathname' # # @author Daniel Burger def to_path Pathname.null end
end
Public Class Methods
Class level rendition of Array#zip.
arrays - List of arrays to zip. [Array<Array>]
Example:
Array.zip([1,2],[3,4]] #=> [[1,3],[2,4]]
Returns arranged array of arrays. [Array<Array>]
Returns an empty array if no arguments are given. [Array]
# File lib/core/facets/array/zip.rb, line 16 def self.zip(*arrays) return [] if arrays.empty? return arrays[0].zip(*arrays[1..-1]) end
Public Instance Methods
Returns the value after the given value. The value before the last is the first. Returns nil if the given value is not in the array.
Examples
sequence = ['a', 'b', 'c'] sequence.after('a') #=> 'b' sequence.after('b') #=> 'c' sequence.after('c') #=> 'a' sequence.after('d') #=> nil
CREDIT: Tyler Rick
# File lib/core/facets/array/before.rb, line 35 def after(value) return nil unless include? value self[(index(value).to_i + 1) % length] end
The `arrange` method produces appropriate ranges from the objects in the array.
Examples
[1,2,3,6,7,8].arrange #=> [1..3, 6..8] [10..15, 16..20, 21, 22].arrange #=> [10..22]
Assumes inclusive ranges (ie. 1..4) and range.first <= range.last.
Works with integers, dates and strings. However, all the objects in the array must be of the same class.
CREDIT: monocle
# File lib/core/facets/array/arrange.rb, line 18 def arrange array = uniq.sort_by { |e| Range === e ? e.first : e } array.inject([]) do |c, value| unless c.empty? last = c.last last_value = (Range === last ? last.last : last) current_value = (Range === value ? value.first : value) if (last_value.succ <=> current_value) == -1 c << value else first = (Range === last ? last.first : last) second = [Range === last ? last.last : last, Range === value ? value.last : value].max c[-1] = [first..second] c.flatten! end else c << value end end end
Calculate the average of an array of numbers
Examples
[].average #=> nil [1, 2, 3].average #=> 2 [3, 12, 57, 85, 15, 89, 33, 7, 22, 54].average #=> 37.7 [1,[2,nil,[3]],nil,4].collapse #=> [1,2,3,4]
# File lib/core/facets/array/average.rb, line 12 def average return nil if empty? self.reduce(:+)/length.to_f end
Returns the value previous to the given value. The value previous to the first is the last. Returns nil if the given value is not in the array.
Examples
sequence = ['a', 'b', 'c'] sequence.before('a') #=> 'c' sequence.before('b') #=> 'a' sequence.before('c') #=> 'b' sequence.before('d') #=> nil
CREDIT: Tyler Rick
# File lib/core/facets/array/before.rb, line 17 def before(value) return nil unless include? value self[(index(value).to_i - 1) % length] end
Simplify an array by flattening it then compacting it.
Examples
[1,[2,nil,[3]],nil,4].collapse #=> [1,2,3,4]
# File lib/core/facets/array/collapse.rb, line 9 def collapse flatten.compact end
# File lib/core/facets/array/collapse.rb, line 13 def collapse! flatten!.compact! end
Get a list of all items that have something in common in terms of the supplied block. If no block is given objects are considered to be in common if they return the same value for Object#hash and if obj1 == obj2.
This can be useful, for instance, in determining all persons that share their last name with another person.
persons.commonality { |person| person.last_name }
The method is similar to group_by which is a standard Ruby method as of 1.9. To get effectively the same results with group_by use `select{ |k,v| v.size > 1 }`.
[1, 2, 2, 3, 4, 4].group_by{ |e| e }.select{ |k,v| v.size > 1 } #=> { 2 => [2, 2], 4 => [4, 4] }
Examples
[1, 2, 2, 3, 4, 4].commonality #=> { 2 => [2, 2], 4 => [4, 4] } ["foo", "bar", "baz"].commonality { |str| str[0] } #=> { 'b' => ["bar", "baz"] }
Returns [Hash] mapping common attribute to those elements.
CREDIT: Florian Gross
# File lib/core/facets/array/commonality.rb, line 29 def commonality(&block) block ||= lambda { |item| item } result = Hash.new { |hash, key| hash[key] = Array.new } each do |item| key = block.call(item) result[key] << item end result.reject! do |key, values| values.size <= 1 end return result end
This is more advanced form of join. It allows for fine control of separators.
NOTE: The old version used to default its separator to “, ” and default the terminating separator to “ and ”. This is no longer the case. You must specifically provide these parameters.
If no paramters are given, it acts like join but will a space separator.
[1,2,3].conjoin #=> "1 2 3"
Use comma+space and 'and' on tail.
[1,2,3].conjoin(', ', ' and ') #=> "1, 2 and 3"
Use comma+space and 'or' on tail using :last option.
[1,2,3].conjoin(', ', :last => ' or ') #=> "1, 2 or 3"
Use semicolon+space and ampersand on tail using index.
[1,2,3].conjoin('; ', -1 => ' & ') #=> "1; 2 & 3"
Can take a block to determine separator.
[1,2,3,4].conjoin{ |i, a, b| i % 2 == 0 ? '.' : '-' } #=> "1.2-3.4"
This makes very esoteric transformation possible.
[1,1,2,2].conjoin{ |i, a, b| a == b ? '=' : ' != ' } #=> "1=1 != 2=2" [1,2,3,4].conjoin{ |i, x, y| "<#{i} #{x} #{y}>" } #=> "1<0 1 2>2<1 2 3>3<2 3 4>4"
There are also spacing options. Providing the :space option pads the separators.
[1,2,3].conjoin(',', '&', :space=>2) #=> "1 , 2 & 3"
And the :spacer option can set an alternate spacing string.
[1,2,3].conjoin('|', '>', :space=>2, :spacer=>'-') #=> "1--|--2-->--3"
CREDIT: Trans
# File lib/core/facets/array/conjoin.rb, line 57 def conjoin(*args, &block) return first.to_s if size < 2 options = (Hash===args.last) ? args.pop : {} spacing = options.delete(:space) || 0 spacer = options.delete(:spacer) || " " space = spacer * spacing.to_i sep = [] if block_given? (size - 1).times do |i| sep << space + yield(i, *slice(i,2)) + space end else separator = args.shift || " " options[-1] = args.shift if args.first options[0] = options.delete(:first) if options.key?(:first) options[-1] = options.delete(:last) if options.key?(:last) separator = space + separator + space sep = [separator] * (size - 1) options.each{|i, s| sep[i] = space + s + space} end zip(sep).join end
Inverse of delete_if.
[1,2,3].delete_unless{ |x| x < 2 } #=> [1]
CREDIT: Daniel Schierbeck
# File lib/core/facets/array/delete_unless.rb, line 10 def delete_unless(&block) delete_if { |element| not block.call(element) } end
Delete multiple values from array.
a = [1,2,3,4] a.delete_values(1,2) #=> [1,2] a #=> [3,4]
CREDIT: Trans
# File lib/core/facets/array/delete_values.rb, line 11 def delete_values(*values) d = [] values.each{ |v| d << delete(v) } d end
Delete multiple values from array given indexes or index range.
a = [1,2,3,4] a.delete_values_at(1,2) #=> [2,3] a #=> [1,4] a = [1,2,3,4] a.delete_values_at(0..2) #=> [1,2,3] a #=> [4]
NOTE: It would be nice to see delete_at incorporate this funcitonaility.
CREDIT: Trans
# File lib/core/facets/array/delete_values.rb, line 32 def delete_values_at(*selectors) idx = [] selectors.each{ |i| case i when Range idx.concat( i.to_a ) else idx << i.to_i end } idx.uniq! dvals = values_at(*idx) idx = (0...size).to_a - idx self.replace( values_at(*idx) ) return dvals end
Divide on matching pattern.
['a1','b1','a2','b2'].divide(/^a/) #=> [['a1','b1'],['a2','b2']] ['a1','b1','a2','b2'].divide(/^b/) #=> [['a1',['b1','a2'],[]'b2']] ['a1','b1','a2','b2'].divide(/^c/) #=> [['a1','b1','a2','b2']]
CREDIT: Trans
# File lib/core/facets/array/divide.rb, line 16 def divide(pattern) memo = [] memo.push [] unless pattern === first each do |obj| memo.push [] if pattern === obj memo.last << obj end memo end
Return list of duplicate elements.
min - The minimum number of duplication necessary for inclusion. [Integer]
Examples:
[1,1,2,3].duplicates #=> [1] [1,1,2,3,2,4,5,4,2].duplicates(3) #=> [2]
CREDIT: Rebort Dober (current implementation) CREDIT: Thibaut Barrère
# File lib/core/facets/array/duplicates.rb, line 16 def duplicates(min=2) h = Hash.new( 0 ) each {|i| h[i] += 1 } h.delete_if{|_,v| v < min}.keys end
Iterate over each slice where the last n values of a preceding slice overlap with the first n values of the following slice. The value of n is specified by the second `overlap` argument.
a, r = [1,2,3,4,5], [] a.each_overlap(2,1) { |x,y| r << [x,y] } r # => [[1,2],[2,3],[3,4],[4,5]]
Returns nothing.
# File lib/core/facets/array/each_overlap.rb, line 13 def each_overlap(slice_size, overlap) if block_given? i = 0 while i + slice_size <= length yield slice(i...i+slice_size) i += (slice_size - overlap) end else to_enum(:each_overlap, slice_size, overlap) end end
Iterate over index and value. The intention of this method is to provide polymorphism with Hash.
# File lib/core/facets/array/each_pair.rb, line 6 def each_pair #:yield: each_with_index {|e, i| yield(i,e) } 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.
e = %w{ a b c d e e e }.entropy ("%.3f" % e) #=> "2.128"
CREDIT: Derek
# File lib/core/facets/array/entropy.rb, line 16 def entropy arr = self 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
Extracts options from a set of arguments. Removes and returns the last element in the array if it's a hash, otherwise returns a blank hash.
def options(*args) args.extract_options! end options(1, 2) # => {} options(1, 2, :a => :b) # => {:a=>:b}
# File lib/core/facets/array/extract_options.rb, line 23 def extract_options! if Hash === last && last.extractable_options? pop else {} end end
Returns elements from `index` until the end.
%w{W o r l d}.from(3) #=> ["l", "d"] %w{W o r l d}.from(9) #=> []
# File lib/core/facets/array/from.rb, line 8 def from(index) return [] if index >= size self[index..-1] 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).
CREDIT: Derek
# File lib/core/facets/array/entropy.rb, line 32 def ideal_entropy arr = self 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
Returns the values in common for an array set (nil, single value/object, or range).
CREDIT: monocle
# File lib/core/facets/array/intersection.rb, line 7 def intersection array = uniq.sort_by { |e| Range === e ? e.first : e } array.inject() do |c, e| f = (Range === c ? c.last : c) v = (Range === e ? e.first : e) case f <=> v when -1 then return nil when 0 then f else if Range === e v..([f, e.last].min) else v end end end end
Determines the sorted middle element.
a = %w{a a b b c c c} a.median #=> "b"
When there are an even number of elements, the greater of the two middle elements is given.
a = %w{a a b b c c c d} a.median #=> "c"
An offset can be supplied to get an element relative to the middle.
a = %w{a a b b c c c d} a.median(-1) #=> "b"
The the array is empty, nil
is returned.
@return [Object] sorted middle element
# File lib/core/facets/array/median.rb, line 23 def median(offset=0) return nil if self.size == 0 tmp = self.sort mid = (tmp.size / 2).to_i + offset tmp[mid] end
In place merge.
a = [1,2] a.merge! [2,3] a #=> [1,2,3]
CREDIT: Trans
# File lib/core/facets/array/merge.rb, line 11 def merge!( other ) self.replace(self.merge(other)) end
Determine the “holes” in the values of an array.
TODO: Better name?
Returns the missing elements in an array set.
CREDIT: monocle
# File lib/core/facets/array/missing.rb, line 13 def missing missing, array = [], arrange i, length = 0, array.size - 1 while i < length x0 = array[i] x1 = array[i+1] c = (Range === x0 ? x0.last : x0) n = (Range === x1 ? x1.first : x1) missing << ( c.succ.succ == n ? c.succ : ((c.succ)..(n.pred)) ) i += 1 end return missing end
In Statistics. mode is the value that occurs most frequently in a given set of data. This method returns an array in case there is a tie.
[:a, :b, :c, :b, :d].mode #=> [:b] [:a, :b, :c, :b, :a].mode #=> [:a, :b]
Returns an Array of most common elements.
@author Robert Klemme
# File lib/core/facets/array/mode.rb, line 14 def mode max = 0 c = Hash.new 0 each {|x| cc = c[x] += 1; max = cc if cc > max} c.select {|k,v| v == max}.map {|k,v| k} end
Returns a list of non-unique elements.
Examples
[1,1,2,2,3,4,5].nonuniq #=> [1,2]
CREDIT: Martin DeMello
# File lib/core/facets/array/nonuniq.rb, line 11 def nonuniq h1 = {} h2 = {} each {|i| h2[i] = true if h1[i] h1[i] = true } h2.keys end
Same as `#nonuniq` but acts in place.
# File lib/core/facets/array/nonuniq.rb, line 23 def nonuniq! self.replace(self.nonuniq) end
Not empty?
[].not_empty? #=> false [1,2].not_empty? #=> true
# File lib/core/facets/array/not_empty.rb, line 8 def not_empty? !empty? end
# File lib/core/facets/object/object_state.rb, line 47 def object_state(data=nil) data ? replace(data) : dup end
Returns a list of elements that occur n
times.
If n
is a Range then returns elements
that occur a number of time within the range.
Examples
[0,1,1,1,3,0,1,2,4].occur(3) #=> [1] [0,1,1,1,3,0,1,2,4].occur(2..4) #=> [0,1]
Returns [Array] of reoccurring elements.
CREDIT: Robert Dober
# File lib/core/facets/array/occur.rb, line 18 def occur(n=nil) #:yield: h = Hash.new(0) each do |i| h[i] += 1 end case n when nil h.delete_if{ |_,v| ! yield(v) }.keys when Range h.delete_if{ |_,v| ! n.include?(v) }.keys else h.delete_if{|_,v| v != n}.keys end end
Create a hash of each uniq element of the array and how many time each appears.
Examples
[:a,:a,:b,:c,:c,:c].occurrence #=> { :a => 2, :b => 1, :c => 3 } [2,2,3,4,4,4].occurrence{|i| i % 2} #=> { 0 => 5, 1 => 1 }
# File lib/core/facets/array/occurrence.rb, line 14 def occurrence h = Hash.new(0) if block_given? each do |e| h[yield(e)] += 1 end else each do |e| h[e] += 1 end end h end
Returns the only element in the array. Raises an IndexError if the array's size is not 1.
[5].only # => 5 expect IndexError do [1,2,3].only end expect IndexError do [].only end
CREDIT: Gavin Sinclair, Noah Gibbs
# File lib/core/facets/array/only.rb, line 18 def only unless size == 1 raise IndexError, "not the only element of array" end first end
Pad an array with a given value
up to a given
length
.
[0,1,2].pad(6,"a") #=> [0,1,2,"a","a","a"]
If length
is a negative number padding will be added to the
beginning of the array.
[0,1,2].pad(-6,"a") #=> ["a","a","a",0,1,2]
CREDIT: Richard Laugesen
# File lib/core/facets/array/pad.rb, line 14 def pad(len, val=nil) return dup if self.size >= len.abs if len < 0 Array.new((len+size).abs,val) + self else self + Array.new(len-size,val) end end
Like pad but changes the array in place.
a = [0,1,2] a.pad!(6,"x") a #=> [0,1,2,"x","x","x"]
CREDIT: Richard Laugesen
# File lib/core/facets/array/pad.rb, line 31 def pad!(len, val=nil) return self if self.size >= len.abs if len < 0 replace Array.new((len+size).abs,val) + self else concat Array.new(len-size,val) end end
Peek at the top of the stack (the end of the array).
a = [1, 2, 3] a.peek #=> 3 a #=> [1, 2, 3]
Or provide an index to inspect the array from back to front.
# File lib/core/facets/array/pull.rb, line 14 def peek(i=0) i = -(i + 1) fetch(i) end
Put an object on the bottom of the stack (front of the array).
a = [2, 3] a.poke(1) a #=> [1, 2, 3]
Or supply an index and poke works like insert.
# File lib/core/facets/array/pull.rb, line 26 def poke(x, i=0) insert(i,x) end
@author Phrogz
# File lib/standard/facets/set.rb, line 24 def power_set if empty? [self] else subset = dup value = [ subset.pop ] subsubs = subset.power_set subsubs.concat( subsubs.map{ |subset| subset + value } ) end end
Generates a hash mapping each unique element in the array to the relative frequency, i.e. the probability, of it appearance.
[:a, :b, :c, :c].probability #=> {:a=> 0.25, :b=>0.25, :c=>0.5}
CREDIT: Brian Schröder
# File lib/core/facets/array/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
Apply a block to array, and recursively apply that block to each sub-array
or types
.
arr = ["a", ["b", "c", nil], nil] arr.recurse{ |a| a.compact! } #=> ["a", ["b", "c"]]
# File lib/core/facets/array/recurse.rb, line 10 def recurse(*types, &block) types = [self.class] if types.empty? a = inject([]) do |array, value| case value when *types array << value.recurse(*types, &block) else array << value end array end yield a end
In place form of recurse.
# File lib/core/facets/array/recurse.rb, line 25 def recurse!(&block) replace(recurse(&block)) end
Apply a method to array, and recursively apply that method to each
sub-array or given types
.
By default the sub-types are passed through unaffected. Passing a block to recursively can be used to change this.
types - List of class types to recurse. [Array<Class>] block - Optional filter procedure to apply on each recursion.
Examples
arr = ["a", ["b", "c"]] arr.recursively.map{ |v| v.to_sym } #=> [:a, [:b, :c]] arr = ["a", ["b", "c"]] arr.recursively{ |a| a.reverse }.map{ |v| v.to_sym } #=> [:a, [:c, :b]]
Returns [Recursor].
# File lib/core/facets/array/recursively.rb, line 27 def recursively(*types, &block) Recursor.new(self, *types, &block) end
Non-destructive form of `Array#delete_values`. Unlike `delete_values` this method returns a new array.
values - List of array elements to reject.
Examples
[1,2,3,4,5].reject_values(2,4) # => [1,3,5]
Returns [Array]
CREDIT: Sean Mackesey
# File lib/core/facets/array/reject_values.rb, line 16 def reject_values(*values) reject { |x| values.include?(x) } end
# File lib/standard/facets/shellwords.rb, line 81 def shelljoin Shellwords.shelljoin(shellwords) end
Convert an array into command line parameters. The array is accepted in the format of Ruby method arguments –ie. [arg1, arg2, …, hash]
# File lib/standard/facets/shellwords.rb, line 74 def shellwords opts, args = *flatten.partition{ |e| Hash === e } opts = opts.inject({}){ |m,h| m.update(h); m } opts.shellwords + args end
Splice acts as a combination of slice! and store. If two arguments are given it calls store. If a single argument is given it calls slice!.
Examples
a = [1,2,3] a.splice(1) #=> 2 a #=> [1,3] a = [1,2,3] a.splice(1,4) #=> 4 a #=> [1,4,3]
Returns [Array].
CREDIT: Trans
# File lib/core/facets/array/splice.rb, line 23 def splice(*args) if args.size == 1 slice!(*args) else store(*args) end end
Split on matching pattern. Unlike divide this does not include matching elements.
Examples
['a1','a2','b1','a3','b2','a4'].split(/^b/) #=> [['a1','a2'],['a3'],['a4']]
Returns list of split-up arrays. [Array<Array>]
# File lib/core/facets/array/split.rb, line 13 def split(pattern) memo = [] sect = [] each do |obj| if pattern === obj memo << sect sect = [] else sect << obj end end memo << sect memo.pop while memo.last == [] memo end
Destructive version of Enumerable#squeeze.
a = [1,2,2,3,3,2,1] a.squeeze! a #=> [1,2,3,2,1] a = [1,2,2,3,3,2,1] a.squeeze!(*[3]) a #=> [1,2,2,3,2,1]
Returns the receiver. [Array]
CREDIT: T. Yamada
# File lib/core/facets/array/squeeze.rb, line 19 def squeeze!(*limited_to) replace(squeeze(*limited_to)) end
Calculate the #standard_deviation of an array of numbers
Examples
[].standard_deviation #=> nil [1, 2, 3].standard_deviation #=> 0.816496580927726 [96, 35, 72, 30, 75, 33, 68, 13, 49, 71].standard_deviation #=> 24.69331893448104 [36, -67, -17, 85, -46, -64, -23, -13, 89, -47].standard_deviation #=> 54.67183918618432 [60.7829, 31.2622, 20.626, 78.8907, 61.5328].standard_deviation #=> 21.428815505053002
# File lib/core/facets/array/standard_deviation.rb, line 15 def standard_deviation return nil if empty? Math.sqrt(variance) end
Iterate over every nth element of an array.
r = [] [:a, :b, :c, :d].step(2) { |x| r << x } r #=> [:b, :d]
Without a block it returns an Enumerator.
[:a, :b, :c, :d].step(1).to_a #=> [:a, :b, :c, :d] [:a, :b, :c, :d].step(2).to_a #=> [:b, :d] [:a, :b, :c, :d].step(3).to_a #=> [:c] [:a, :b, :c, :d].step(5).to_a #=> []
CREDIT: Ryan Duryea
# File lib/core/facets/array/step.rb, line 18 def step(n) #:yield: if block_given? ((n - 1)...size).step(n).each do |i| yield(fetch(i)) end else Enumerator.new(size / n) do |y| ((n - 1)...self.size).step(n).each { |i| y << fetch(i) } end end end
Fetch values from a start index thru an end index.
[1,2,3,4,5].thru(2) #=> [1,2,3] [1,2,3,4,5].thru(4) #=> [1,2,3,4,5] [1,2,3,4,5].thru(0,2) #=> [1,2,3] [1,2,3,4,5].thru(2,4) #=> [3,4,5]
# File lib/core/facets/array/from.rb, line 21 def thru(from, to=nil) from, to = 0, from unless to return [] if from >= size self[from..to] end
Boolean conversion for not empty?
# File lib/core/facets/boolean.rb, line 110 def to_b ! self.empty? end
Convert an associative array to a Hash.
Examples
[[:a, 1], [:b, 2]].to_h #=> {:a=>1, :b=>2}
Returns [Hash].
# File lib/core/facets/array/to_h.rb, line 12 def to_h h = {} each{ |(k,v)| h[k] = v } h end
Convert array to Pathname instance.
@standard
require 'facets/pathname'
# File lib/standard/facets/pathname/to_path.rb, line 24 def to_path Pathname.new(join('/')) end
Convert an array into a tuple.
# File lib/standard/facets/tuple.rb, line 276 def to_t Tuple.cast_from_array( self ) end
Construct a new array created by traversing the array and its sub-arrays, executing the given block on the elements.
Examples
h = ["A", "B", ["X", "Y"]] g = h.traverse{ |e| e.downcase } g #=> ["a", "b", ["x", "y"]]
This is the same as recursive.map
and will likely be
deprecated in the future because of it.
Returns new array. [Array]
CREDIT: Trans
# File lib/core/facets/array/traverse.rb, line 19 def traverse(&block) if block_given? map do |e| if e.respond_to?(:to_ary) e.to_ary.traverse(&block) else block.call(e) end end else to_enum(:traverse) end end
Like recursive_map, but will change the array in place.
Examples:
h = ["A", "B", ["X", "Y"]] h.traverse!{ |e| e.downcase } h #=> ["a", "b", ["x", "y"]]
Returns self. [Array]
CREDIT: Trans
# File lib/core/facets/array/traverse.rb, line 45 def traverse!(&block) replace(traverse(&block)) end
Like uniq, but determines uniqueness based on a given block. As can be seen in the following examples, order is significant.
Examples
a = (-5..5).to_a a.uniq_by!{ |i| i*i } a #=> [-5, -4, -3, -2, -1, 0] a = (-5..5).to_a.reverse a.uniq_by!{ |i| i*i } a #=> [5, 4, 3, 2, 1, 0]
Returns [Array] of unique elements.
# File lib/core/facets/array/uniq_by.rb, line 18 def uniq_by! #:yield: h = {} replace( inject([]){|a,x| h[yield(x)] ||= a << x} ) end
Enumerates permutation of Array. Unlike Array#permutation, there are no duplicates in generated permutations. Instead, elements must be comparable.
[1,1,2,2,3].unique_permutation(2).to_a #=> [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2]] # Note: [1,1,2,2,3].permutation(2).to_a #=> [[1, 1], [1, 2], [1, 2], [1, 3], [1, 1], [1, 2], [1, 2], [1, 3], [2, 1], [2, 1], [2, 2], [2, 3], [2, 1], [2, 1], [2, 2], [2, 3], [3, 1], [3, 1], [3, 2], [3, 2]]
CREDIT: T. Yamada
# File lib/core/facets/array/unique_permutation.rb, line 13 def unique_permutation(n=self.size) return to_enum(:unique_permutation,n) unless block_given? return if n<0||self.size<n a=self.sort # sort is O(nlogn), so I believe this is not so costly. (Also sort is not destructive) yield a[0,n] loop{ a=a[0,n]+a[n..-1].reverse k=(a.size-2).downto(0).find{|i|a[i]<a[i+1]} break if !k l=(a.size-1).downto(k+1).find{|i|a[k]<a[i]} a[k],a[l]=a[l],a[k] a=a[0,k+1]+a[k+1..-1].reverse yield a[0,n] } end
Calculate the variance of an array of numbers
Examples
[].variance #=> nil [1, 2, 3].variance #=> 0.6666666666666666 [96, 35, 72, 30, 75, 33, 68, 13, 49, 71].variance #=> 609.76 [36, -67, -17, 85, -46, -64, -23, -13, 89, -47].variance #=> 2989.0099999999993 [60.7829, 31.2622, 20.626, 78.8907, 61.5328].variance #=> 459.1941339495999
# File lib/core/facets/array/variance.rb, line 15 def variance avg = average map {|n| (n - avg) ** 2 }.average end