class Array

Convert and array into a tuple.

Public Instance Methods

**(*enums)

Operator alias for cross-product.

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

CREDIT: Trans

Alias for: product
combination(k=2) { |values_at(*idx)| ... } click to toggle source

Yields the block to each unique combination of n elements.

a = %w|a b c d|
a.combination(3)

produces

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

CREDIT: Florian Gross

# File lib/core/facets/array/combination.rb, line 21
def combination(k=2)
  if block_given?
    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
  else
    to_enum(:combination, k)
  end
end
conjoin(*args) { |i, *slice(i,2)| ... } click to toggle source

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.

[1,2,3].conjoin
=> "123"

[1,2,3].conjoin(', ', ' and ')
=> "1, 2 and 3

[1,2,3].conjoin(', ', :last => ' or ')
=> "1, 2 or 3

[1,2,3].conjoin('; ', -1 => ' & ')
=> "1; 2 & 3

[1,2,3,4].conjoin{ |i, a, b| i % 2 == 0 ? '.' : '-' }
=> "1.2-3.4"

[1,1,2,2].conjoin{ |i, a, b| a == b ? '=' : '!=' }
=> "1=1!=2=2"

CREDIT: Trans

# File lib/core/facets/array/conjoin.rb, line 30
def conjoin(*args, &block)
  return first.to_s if size < 2

  sep = []

  if block_given?
    (size - 1).times do |i|
      sep << yield(i, *slice(i,2))
    end
  else
    options   = (Hash===args.last) ? args.pop : {}
    separator = args.shift || ""
    options[-1] = args.shift unless args.empty?

    sep = [separator] * (size - 1)

    if options.key?(:last)
      options[-1] = options.delete(:last)
    end

    options[-1] ||= " and "

    options.each{|i, s| sep[i] = s}
  end
  zip(sep).join
end
delete_unless(&block) click to toggle source

Inverse of delete_if.

[1,2,3].delete_unless{ |x| x < 2 }
=> [1,2]

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_values(*values) click to toggle source

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_values_at(*selectors) click to toggle source

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
index(obj=nil, &block) click to toggle source

Allows index to accept a block.

OVERRIDE! This is one of the bery few core overrides in Facets.

# File lib/core/facets/array/index.rb, line 14
def index(obj=nil, &block)
  if block_given?
    _facets_index(find(&block))
  else
    _facets_index(obj)
  end
end
merge!( other ) click to toggle source

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
not_empty?() click to toggle source

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
object_state(data=nil) click to toggle source
# File lib/core/facets/kernel/object_state.rb, line 31
def object_state(data=nil)
  data ? replace(data) : dup
end
only() click to toggle source

Returns the only element in the array. Raises an IndexError if the array's size is not 1.

[5].only      # -> 5
[1,2,3].only  # -> IndexError
[].only       # -> IndexError

CREDIT: Gavin Sinclair, Noah Gibbs

# File lib/core/facets/array/only.rb, line 12
def only
  unless size == 1
    raise IndexError, "Array#only called on non-single-element array"
  end
  first
end
pad(len, val=nil) click to toggle source

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
pad!(len, val=nil) click to toggle source

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
permutation(n=size) { || ... } click to toggle source

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

CREDIT: Shin-ichiro Hara

# File lib/core/facets/array/permutation.rb, line 11
def permutation(n=size)
  if size < n or n < 0
  elsif n == 0
    yield([])
  else
    self[1..-1].permutation(n - 1) do |x|
      (0...n).each do |i|
        yield(x[0...i] + [first] + x[i..-1])
      end
    end
    self[1..-1].permutation(n) do |x|
      yield(x)
    end
  end
end
power_set() click to toggle source
# File lib/more/facets/set.rb, line 16
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
product(*enums) click to toggle source

Provides the cartesian product of two or more arrays.

a = []
[1,2].product([4,5])
a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]

CREDIT: Thomas Hafner

# File lib/core/facets/array/product.rb, line 13
def product(*enums)
  enums.unshift self
  result = [[]]
  while [] != enums
    t, result = result, []
    b, *enums = enums
    t.each do |a|
      b.each do |n|
        result << a + [n]
      end
    end
  end
  result
end
Also aliased as: **
recursively() { |a| ... } click to toggle source

Apply a block to array, and recursively apply that block to each subarray.

arr = ["a", ["b", "c", nil], nil]
arr.recursively{|a| a.compact! }
=> ["a", ["b", "c"]]

TODO: Can this be generalized in Enumerbale?

# File lib/core/facets/array/recursively.rb, line 12
def recursively(&block)
  a = inject([]) do |array, value|
    if value.is_a?(Array)
      array << value.recursively(&block)
    else
      array << value
    end
    array
  end
  yield a
end
recursively!(&block) click to toggle source

In place form of recursively.

# File lib/core/facets/array/recursively.rb, line 26
def recursively!(&block)
  replace(recursively(&block))
end
rotate(n=1) click to toggle source

Rotates an array's elements from back to front n times.

[1,2,3].rotate      #=> [3,1,2]
[3,1,2].rotate      #=> [2,3,1]
[3,1,2].rotate      #=> [1,2,3]
[1,2,3].rotate(3)   #=> [1,2,3]

A negative parameter reverses the order from front to back.

[1,2,3].rotate(-1)  #=> [2,3,1]

CREDIT: Florian Gross, Thomas Sawyer

# File lib/core/facets/array/rotate.rb, line 16
def rotate(n=1)
  self.dup.rotate!(n)
end
rotate!(n=1) click to toggle source

Same as rotate, but acts in place.

a = [1,2,3]
a.rotate!
a  #=> [3,1,2]

CREDIT: Florian Gross, Thomas Sawyer

# File lib/core/facets/array/rotate.rb, line 28
def rotate!(n=1)
  n = n.to_int
  return self if (n == 0 or self.empty?)
  if n > 0
    n.abs.times{ self.unshift( self.pop ) }
  else
    n.abs.times{ self.push( self.shift ) }
  end
  self
end
select!() { || ... } click to toggle source

As with select but modifies the Array in place.

a = [1,2,3,4,5,6,7,8,9,10]
a.select!{ |e| e % 2 == 0 }
a  #=> [2,4,6,8,10]

CREDIT: Gavin Sinclair

# File lib/core/facets/array/select.rb, line 11
def select!  # :yield:
  reject!{ |e| not yield(e) }
end
shelljoin() click to toggle source
# File lib/more/facets/shellwords.rb, line 28
def shelljoin
  Shellwords.shelljoin(shellwords)
end
shellwords() click to toggle source

Convert an array into command line parameters. The array is accepted in the format of Ruby method arguments –ie. [arg1, arg2, …, hash]

# File lib/more/facets/shellwords.rb, line 22
def shellwords
  opts, args = *flatten.partition{ |e| Hash === e }
  opts = opts.inject({}){ |m,h| m.update(h); m }
  opts.shellwords + args
end
splice(*args) click to toggle source

Splice acts a combination of slice! and store. If two arguments are given it calls store. If a single argument is given it calls slice!.

a = [1,2,3]
a.splice(1)    #=> 2
a              #=> [1,3]

a = [1,2,3]
a.splice(1,4)  #=> 4
a              #=>[1,4,3]

CREDIT: Trans

# File lib/core/facets/array/splice.rb, line 17
def splice(*args)
  if args.size == 1
    slice!(*args)
  else
    store(*args)
  end
end
to_b() click to toggle source

Boolean conversion for not empty?

# File lib/core/facets/boolean.rb, line 60
def to_b
  ! self.empty?
end
to_h(mode=nil) click to toggle source

Converts an array into a hash. Converting an array into a hash is not a one-to-one conversion, for this reason to_h examines at the array being converted and then dispatches the conversion to the most sutiable specialized function. There are three possiblities for this.

If the array is a collection of perfect pairs, like that which Hash#to_a generates, then conversion is handled by to_h_flat.

a = [ [:a,1], [:b,2] ]
a.to_h  #=> { :a=>1, :b=>2 }

If the array contains only arrays, but are not perfect pairs, then to_h_multi is called.

a = [ [:a,1,2], [:b,2], [:c], [:d] ]
a.to_h  #=> { :a=>[1,2], :b=>[2], :c=>[], :d=>[] }

If the array contians objects other then arrays then the to_h_splat method is called.

a = [ [:a,1,2], 2, :b, [:c,3], 9 ]
a.to_h  #=> { [:a,1,2]=>2, :b=>[:c,3], 9=>nil }

Finally, a particular dispatch can be forced by specifying the mode of conversion, eg. :multi, :splat, :flat, :assoc, etc.

Setting mode to true is the same as setting it :multi. This has been left in for backward compatability.

NOTE: The use of a values parameter has been deprecated because that functionality is as simple as:

array1.zip(array2).to_h

CREDIT: Robert Klemme CREDIT: Trans

# File lib/core/facets/to_hash.rb, line 52
def to_h(mode=nil)
  case mode
  when :splat
    return to_h_splat
  when :flat
    return to_h_flat
  when :multi, true
    return to_h_multi
  when :assoc
    return to_h_assoc
  else
    return to_h_auto
  end
end
to_h_assoc() click to toggle source

When a mixed or multi-element accociative array is used, the result is as follows:

a = [ [:a,1,2], [:b,2], [:c], :d ]
a.to_h  #=> { :a=>[1,2], :b=>[2], :c=>[], :d=>[] }

If the first entry of any subelements are the same, then the value will be set to the last occuring value.

a = [ :x, [:x], [:x,1,2], [:x,3], [:x,4] ]
a.to_h_assoc  #=> { :x=>4 }
# File lib/core/facets/to_hash.rb, line 156
def to_h_assoc
  h = {}
  each do |k,*v| 
    h[k] = v
  end
  h
end
to_h_auto() click to toggle source

Converts an array into a hash. Converting an array into a hash is not a one-to-one conversion, for this reason to_h examines at the array being converted and then dispatches the conversion to the most sutiable specialized function. There are three possiblities for this.

If the array is a collection of perfect pairs, like that which Hash#to_a generates, then conversion is handled by to_h_flat.

a = [ [:a,1], [:b,2] ]
a.to_h  #=> { :a=>1, :b=>2 }

If the array contains only arrays, but are not perfect pairs, then to_h_multi is called.

a = [ [:a,1,2], [:b,2], [:c], [:d] ]
a.to_h  #=> { :a=>[1,2], :b=>[2], :c=>[], :d=>[] }

If the array contians objects other then arrays then the to_h_splat method is called.

a = [ [:a,1,2], 2, :b, [:c,3], 9 ]
a.to_h  #=> { [:a,1,2]=>2, :b=>[:c,3], 9=>nil }
# File lib/core/facets/to_hash.rb, line 92
def to_h_auto
  pairs = true
  mixed = false

  each do |e|
    case e
    when Array
      pairs = false if e.size > 2
    else
      mixed = true
    end
  end

  if mixed
    to_h_splat
  elsif pairs
    to_h_flat
  else
    to_h_multi
  end
end
to_h_flat() click to toggle source

This is equivalent to Hash, but it will pad the array with a nil object if there are not an even number of elements.

a = [:a,1,[:b,2,:c]]
a.to_h_flat  #=> { :a=>1, :b=>2, :c=>nil }
# File lib/core/facets/to_hash.rb, line 134
def to_h_flat
  a = flatten
  a << nil if a.size % 2 == 1
  Hash[*a]
end
to_h_multi() click to toggle source

When a mixed or multi-element accociative array is used, the result is as follows:

a = [ [:a,1,2], [:b,2], [:c], :d ]
a.to_h  #=> { :a=>[1,2], :b=>[2], :c=>[], :d=>[] }

If the first entry of the subelements is the same, then the values will be merged using concat.

a = [ [:a,1,2], [:a,3], [:a,4], [:a], :a ]
a.to_h_multi  #=> { :a=>[1,2,3,4] }
# File lib/core/facets/to_hash.rb, line 176
def to_h_multi
  h = {}
  each do |k,*v| 
    h[k] ||= []
    h[k].concat(v)
  end
  h
end
to_h_splat() click to toggle source

This is equivalent to Hash, but it will pad the array with a nil object if there are not an even number of elements.

a = [:a,1,:b,2,:c]
a.to_h_splat  #=> { :a=>1, :b=>2, :c=>nil }
# File lib/core/facets/to_hash.rb, line 121
def to_h_splat
  a = dup
  a << nil if a.size % 2 == 1
  Hash[*a]
end
to_t() click to toggle source
# File lib/more/facets/tuple.rb, line 320
def to_t
  Tuple.cast_from_array( self )
end
traverse() { |item| ... } click to toggle source
# File lib/core/facets/array/traverse.rb, line 5
def traverse(&block)
  map do |item|
    if item.is_a?(self.class)
      item.traverse(&block)
    else
      yield item
    end
  end
end
traverse!(&block) click to toggle source
# File lib/core/facets/array/traverse.rb, line 17
def traverse!(&block)
  replace(traverse(&block))
end