Methods
Included Modules
Public Instance methods
**(*enums, &block)

Alias for product

**(*enums, &block)

Alias for product

combination(k=2) {|s.values_at(*idx)| ...}

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
combination(k=2) {|s.values_at(*idx)| ...}

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)| ...}

This is more advnaced form of join. It allows for fine control of separators.

NOTE: The old version used to default it‘s 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
conjoin(*args) {|i, *slice(i,2)| ...}

This is more advnaced form of join. It allows for fine control of separators.

NOTE: The old version used to default it‘s 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)

Inverse of delete_if.

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

 CREDIT: Daniel Schierbeck
# File lib/core/facets/array/delete.rb, line 10
  def delete_unless(&block)
    delete_if { |element| not block.call(element) }
  end
delete_unless(&block)

Inverse of delete_if.

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

 CREDIT: Daniel Schierbeck
# File lib/core/facets/array/delete.rb, line 10
  def delete_unless(&block)
    delete_if { |element| not block.call(element) }
  end
delete_values(*values)

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.rb, line 22
  def delete_values(*values)
    d = []
    values.each{ |v| d << delete(v) }
    d
  end
delete_values(*values)

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.rb, line 22
  def delete_values(*values)
    d = []
    values.each{ |v| d << delete(v) }
    d
  end
delete_values_at(*selectors)

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.rb, line 43
  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
delete_values_at(*selectors)

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.rb, line 43
  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
merge!( other )

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
merge!( other )

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?()

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
not_empty?()

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
only()

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
 CREDIT: Noah Gibbs
# File lib/core/facets/array/only.rb, line 13
  def only
    unless size == 1
      raise IndexError, "Array#only called on non-single-element array"
    end
    first
  end
only()

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
 CREDIT: Noah Gibbs
# File lib/core/facets/array/only.rb, line 13
  def only
    unless size == 1
      raise IndexError, "Array#only called on non-single-element array"
    end
    first
  end
pad(len, val=nil)

Pad an array with a given value upto 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)

Pad an array with a given value upto 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)

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

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) {|[]| ...}

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
permutation(n=size) {|[]| ...}

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
product(*enums, &block)

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

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

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

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

 CREDIT: Thomas Hafner
# File lib/core/facets/array/product.rb, line 21
    def product(*enums, &block)
      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
      if block_given?
        result.each{ |e| block.call(e) }
      else
        result
      end
    end
product(*enums, &block)

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

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

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

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

 CREDIT: Thomas Hafner
This method is also aliased as ** **
# File lib/core/facets/array/product.rb, line 21
    def product(*enums, &block)
      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
      if block_given?
        result.each{ |e| block.call(e) }
      else
        result
      end
    end
recursively() {|a| ...}

Apply a block to hash, and recursively apply that block to each subhash.

  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() {|a| ...}

Apply a block to hash, and recursively apply that block to each subhash.

  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)

In place form of recursively.

# File lib/core/facets/array/recursively.rb, line 26
  def recursively!(&block)
    replace(recursively(&block))
  end
recursively!(&block)

In place form of recursively.

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

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
 CREDIT: Thomas Sawyer
# File lib/core/facets/array/rotate.rb, line 17
  def rotate(n=1)
    self.dup.rotate!(n)
  end
rotate(n=1)

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
 CREDIT: Thomas Sawyer
# File lib/core/facets/array/rotate.rb, line 17
  def rotate(n=1)
    self.dup.rotate!(n)
  end
rotate!(n=1)

Same as rotate, but acts in place.

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

 CREDIT: Florian Gross
 CREDIT: Thomas Sawyer
# File lib/core/facets/array/rotate.rb, line 30
  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
rotate!(n=1)

Same as rotate, but acts in place.

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

 CREDIT: Florian Gross
 CREDIT: Thomas Sawyer
# File lib/core/facets/array/rotate.rb, line 30
  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!( {|| ...}

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
select!( {|| ...}

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
splice(*args)

Splice acts a combination of slice! and store. If two arguments are given it calls store. If a single argument is give 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
splice(*args)

Splice acts a combination of slice! and store. If two arguments are given it calls store. If a single argument is give 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()

Boolean conversion for not empty?

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

Converts a two-element associative array into a hash.

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

If arrayed is set it will maintain trailing arrays.

  a = [ [:a,1,2], [:b,3] ]
  a.to_h(true)  #=> { :a=>[1,2], :b=>[3] }

Note that the use of a values parameter has been deprecated because that functionality is as simple as:

  array1.zip(array2).to_h

 CREDIT: Trans
# File lib/core/facets/to_hash.rb, line 20
  def to_h(arrayed=nil)
    h = {}
    if arrayed #or (flatten.size % 2 == 1)
      #each{ |e| h[e.first] = e.slice(1..-1) }
      each{ |k,*v| h[k] = v }
    else
      #h = Hash[*flatten(1)] # TODO Use in 1.9 instead.
      ary = []
      each do |a|
        Array===a ? ary.concat(a) : ary << a
      end
      h = Hash[*ary]
    end
    h
  end
traverse() {|item| ...}
# 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() {|item| ...}
# 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)
# File lib/core/facets/array/traverse.rb, line 17
  def traverse!(&block)
    replace(traverse(&block))
  end
traverse!(&block)
# File lib/core/facets/array/traverse.rb, line 17
  def traverse!(&block)
    replace(traverse(&block))
  end