Convert and array into a tuple.
Operator alias for cross-product.
a = [1,2] ** [4,5] a #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
CREDIT: Trans
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
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
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 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
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
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? #=> 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/kernel/object_state.rb, line 31 def object_state(data=nil) data ? replace(data) : dup end
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 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
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
# 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
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
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
In place form of recursively.
# File lib/core/facets/array/recursively.rb, line 26 def recursively!(&block) replace(recursively(&block)) end
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
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
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
# File lib/more/facets/shellwords.rb, line 28 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/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 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
Boolean conversion for not empty?
# File lib/core/facets/boolean.rb, line 60 def to_b ! self.empty? end
# File lib/more/facets/tuple.rb, line 320 def to_t Tuple.cast_from_array( self ) end
# 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
# File lib/core/facets/array/traverse.rb, line 17 def traverse!(&block) replace(traverse(&block)) end