Convert and array into a tuple.
Simplify an array by flattening it then compacting it.
[1,[2,nil,[3]],nil,4].collapse #=> [1,2,3,4]
# File lib/core/facets/enumerable/collapse.rb, line 7 7: def collapse 8: flatten.compact 9: end
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
21: def combination(k=2)
22: if block_given?
23: s = to_a
24: n = s.size
25: return unless (1..n) === k
26: idx = (0...k).to_a
27: loop do
28: yield s.values_at(*idx)
29: i = k - 1
30: i -= 1 while idx[i] == n - k + i
31: break if i < 0
32: idx[i] += 1
33: (i + 1 ... k).each {|j| idx[j] = idx[i] + j - i}
34: end
35: else
36: to_enum(:combination, k)
37: end
38: end
This is more advanced form of #. 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
30: def conjoin(*args, &block)
31: return first.to_s if size < 2
32:
33: sep = []
34:
35: if block_given?
36: (size - 1).times do |i|
37: sep << yield(i, *slice(i,2))
38: end
39: else
40: options = (Hash===args.last) ? args.pop : {}
41: separator = args.shift || ""
42: options[1] = args.shift unless args.empty?
43:
44: sep = [separator] * (size - 1)
45:
46: if options.key?(:last)
47: options[1] = options.delete(:last)
48: end
49:
50: options[1] ||= " and "
51:
52: options.each{|i, s| sep[i] = s}
53: end
54: zip(sep).join
55: end
Inverse of #.
[1,2,3].delete_unless{ |x| x < 2 }
=> [1,2]
CREDIT: Daniel Schierbeck
# File lib/core/facets/array/delete_unless.rb, line 10
10: def delete_unless(&block)
11: delete_if { |element| not block.call(element) }
12: 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
11: def delete_values(*values)
12: d = []
13: values.each{ |v| d << delete(v) }
14: d
15: 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 # incorporate this funcitonaility.
CREDIT: Trans
# File lib/core/facets/array/delete_values.rb, line 32
32: def delete_values_at(*selectors)
33: idx = []
34: selectors.each{ |i|
35: case i
36: when Range
37: idx.concat( i.to_a )
38: else
39: idx << i.to_i
40: end
41: }
42: idx.uniq!
43: dvals = values_at(*idx)
44: idx = (0...size).to_a - idx
45: self.replace( values_at(*idx) )
46: return dvals
47: end
Allows # 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
14: def index(obj=nil, &block)
15: if block_given?
16: _facets_index(find(&block))
17: else
18: _facets_index(obj)
19: end
20: end
In place #.
a = [1,2] a.merge! [2,3] a => [1,2,3]
CREDIT: Trans
# File lib/core/facets/array/merge.rb, line 11
11: def merge!( other )
12: self.replace(self.merge(other))
13: end
Not empty?
[].not_empty? #=> false [1,2].not_empty? #=> true
# File lib/core/facets/array/not_empty.rb, line 8
8: def not_empty?
9: !empty?
10: end
# File lib/core/facets/kernel/object_state.rb, line 31
31: def object_state(data=nil)
32: data ? replace(data) : dup
33: 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
12: def only
13: unless size == 1
14: raise IndexError, "Array#only called on non-single-element array"
15: end
16: first
17: 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
14: def pad(len, val=nil)
15: return dup if self.size >= len.abs
16: if len < 0
17: Array.new((len+size).abs,val) + self
18: else
19: self + Array.new(len-size,val)
20: end
21: end
Like # 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
31: def pad!(len, val=nil)
32: return self if self.size >= len.abs
33: if len < 0
34: replace Array.new((len+size).abs,val) + self
35: else
36: concat Array.new(len-size,val)
37: end
38: 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
11: def permutation(n=size)
12: if size < n or n < 0
13: elsif n == 0
14: yield([])
15: else
16: self[1..1].permutation(n - 1) do |x|
17: (0...n).each do |i|
18: yield(x[0...i] + [first] + x[i..1])
19: end
20: end
21: self[1..1].permutation(n) do |x|
22: yield(x)
23: end
24: end
25: end
# File lib/more/facets/set.rb, line 16
16: def power_set
17: if empty?
18: [self]
19: else
20: subset = dup
21: value = [ subset.pop ]
22: subsubs = subset.power_set
23: subsubs.concat( subsubs.map{ |subset| subset + value } )
24: end
25: 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
13: def product(*enums)
14: enums.unshift self
15: result = [[]]
16: while [] != enums
17: t, result = result, []
18: b, *enums = enums
19: t.each do |a|
20: b.each do |n|
21: result << a + [n]
22: end
23: end
24: end
25: result
26: 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"]]
# File lib/core/facets/array/recursive.rb, line 12
12: def recursive(opts={}, &block)
13: if block
14: a = inject([]) do |array, value|
15: if value.is_a?(Array)
16: array << value.recursive(&block)
17: else
18: array << value
19: end
20: array
21: end
22: yield a
23: else
24: Recursor.new(self, opts)
25: end
26: end
In place form of #.
# File lib/core/facets/array/recursive.rb, line 30
30: def recursive!(&block)
31: r = recursive(&block)
32: raise TypeError unless Array === r
33: replace(r)
34: 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"]]
# File lib/core/facets/array/recursively.rb, line 10
10: def recursively(&block)
11: warn "Use #recusive instead of #recursively for future versions"
12: a = inject([]) do |array, value|
13: if value.is_a?(Array)
14: array << value.recursively(&block)
15: else
16: array << value
17: end
18: array
19: end
20: yield a
21: end
In place form of #.
# File lib/core/facets/array/recursively.rb, line 25
25: def recursively!(&block)
26: replace(recursively(&block))
27: 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
16: def rotate(n=1)
17: self.dup.rotate!(n)
18: end
Same as #, 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
28: def rotate!(n=1)
29: n = n.to_int
30: return self if (n == 0 or self.empty?)
31: if n > 0
32: n.abs.times{ self.unshift( self.pop ) }
33: else
34: n.abs.times{ self.push( self.shift ) }
35: end
36: self
37: end
As with # 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
11: def select! # :yield:
12: reject!{ |e| not yield(e) }
13: end
# File lib/more/facets/shellwords.rb, line 28
28: def shelljoin
29: Shellwords.shelljoin(shellwords)
30: 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
22: def shellwords
23: opts, args = *flatten.partition{ |e| Hash === e }
24: opts = opts.inject({}){ |m,h| m.update(h); m }
25: opts.shellwords + args
26: end
Splice acts a combination of # and #. If two arguments are given it calls #. 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
17: def splice(*args)
18: if args.size == 1
19: slice!(*args)
20: else
21: store(*args)
22: end
23: end
Boolean conversion for not empty?
# File lib/core/facets/boolean.rb, line 132
132: def to_b
133: ! self.empty?
134: end
Converts an array into a hash. Converting an array into a hash is not a one-to-one conversion, for this reason # 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 #.
a = [ [:a,1], [:b,2] ]
a.to_h #=> { :a=>1, :b=>2 }
If the array contains only arrays, but are not perfect pairs, then # 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 # 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
52: def to_h(mode=nil)
53: case mode
54: when :splat
55: return to_h_splat
56: when :flat
57: return to_h_flat
58: when :multi, true
59: return to_h_multi
60: when :assoc
61: return to_h_assoc
62: else
63: return to_h_auto
64: end
65: end
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
156: def to_h_assoc
157: h = {}
158: each do |k,*v|
159: h[k] = v
160: end
161: h
162: end
Converts an array into a hash. Converting an array into a hash is not a one-to-one conversion, for this reason # 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 #.
a = [ [:a,1], [:b,2] ]
a.to_h #=> { :a=>1, :b=>2 }
If the array contains only arrays, but are not perfect pairs, then # 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 # 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
92: def to_h_auto
93: pairs = true
94: mixed = false
95:
96: each do |e|
97: case e
98: when Array
99: pairs = false if e.size > 2
100: else
101: mixed = true
102: end
103: end
104:
105: if mixed
106: to_h_splat
107: elsif pairs
108: to_h_flat
109: else
110: to_h_multi
111: end
112: end
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
134: def to_h_flat
135: a = flatten
136: a << nil if a.size % 2 == 1
137: Hash[*a]
138: end
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 #.
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
176: def to_h_multi
177: h = {}
178: each do |k,*v|
179: h[k] ||= []
180: h[k].concat(v)
181: end
182: h
183: end
This is equivalent to Hash[*array], 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
121: def to_h_splat
122: a = dup
123: a << nil if a.size % 2 == 1
124: Hash[*a]
125: end
# File lib/more/facets/tuple.rb, line 320
320: def to_t
321: Tuple.cast_from_array( self )
322: end
Returns a new array created by traversing the array and its sub-arrays, executing the given block on the elements.
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.
CREDIT: Trans
# File lib/core/facets/array/traverse.rb, line 17
17: def traverse(&block)
18: if block_given?
19: map do |e|
20: if e.respond_to?(:to_ary)
21: e.to_ary.traverse(&block)
22: else
23: block.call(e)
24: end
25: end
26: else
27: to_enum(:traverse)
28: end
29: end
Like #, but will change the array in place.
# File lib/core/facets/array/traverse.rb, line 34
34: def traverse!(&block)
35: replace(traverse(&block))
36: end
Like #, but determines uniqueness based on a given block.
(-5..5).to_a.uniq_by {|i| i*i }
produces
[-5, -4, -3, -2, -1, 0]
# File lib/core/facets/array/uniq_by.rb, line 13
13: def uniq_by! #:yield:
14: h = {}; replace(inject([]){|a,x| h[yield(x)] ||= a << x})
15: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.