# File lib/backports/1.9.1/array.rb, line 4 def try_convert(obj) Backports.try_convert(obj, Array, :to_ary) end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 3 def combination(num) num = Backports.coerce_to_int(num) return to_enum(:combination, num) unless block_given? return self unless (0..size).include? num # Implementation note: slightly tricky. # Example: self = 1..7, num = 3 picks = (0...num).to_a # picks start at 0, 1, 2 max_index = ((size-num)...size).to_a # max (index for a given pick) is [4, 5, 6] pick_max_pairs = picks.zip(max_index).reverse # pick_max_pairs = [[2, 6], [1, 5], [0, 4]] lookup = pick_max_pairs.find(Proc.new{return self}) loop do yield values_at(*picks) move = lookup.each{|pick, max| picks[pick] < max}.first new_index = picks[move] + 1 picks[move...num] = (new_index...(new_index+num-move)).to_a end end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 22 def cycle(n = nil) return to_enum(:cycle, n) unless block_given? if n.nil? each{|e| yield e } until false else n = Backports.coerce_to_int(n) n.times{each{|e| yield e }} end nil end
See official documentation
# File lib/backports/rails/array.rb, line 3 def extract_options! last.is_a?(::Hash) ? pop : {} end
Recursively flatten any contained Arrays into an one-dimensional result. Adapted from rubinius'
# File lib/backports/1.8.7/array.rb, line 41 def flatten_with_optional_argument(level=-1) dup.flatten!(level) || self end
Flattens self in place as flatten. If no changes are made, returns nil, otherwise self. Adapted from rubinius'
# File lib/backports/1.8.7/array.rb, line 48 def flatten_with_optional_argument!(level=-1) level = Backports.coerce_to_int(level) return flatten_without_optional_argument! unless level >= 0 ret, out = nil, [] ret = recursively_flatten_finite(self, out, level) replace(out) if ret ret end
# File lib/backports/1.8.7/array.rb, line 84 def index_with_block(*arg) return index_without_block(*arg) unless block_given? && arg.empty? each_with_index{|o,i| return i if yield o} return nil end
Standard in Ruby 1.9.2 See official documentation
# File lib/backports/1.9.2/array.rb, line 3 def keep_if return to_enum(:keep_if) unless block_given? delete_if{|elem| !yield elem} end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 94 def permutation(num = Backports::Undefined) return to_enum(:permutation, num) unless block_given? num = num.equal?(Backports::Undefined) ? size : Backports.coerce_to_int(num) return self unless (0..size).include? num final_lambda = lambda do |partial, remain| yield partial end outer_lambda = num.times.inject(final_lambda) do |proc, ignore| lambda do |partial, remain| remain.each_with_index do |val, i| new_remain = remain.dup new_remain.delete_at(i) proc.call(partial.dup << val, new_remain) end end end outer_lambda.call([], self) end
# File lib/backports/1.8.7/array.rb, line 120 def pop_with_optional_argument(n = Backports::Undefined) return pop_without_optional_argument if n == Backports::Undefined n = Backports.coerce_to_int(n) raise ArgumentError, "negative array size" if n < 0 first = size - n first = 0 if first < 0 slice!(first..size).to_a end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 132 def product(*arg) # Implementation notes: We build a block that will generate all the combinations # by building it up successively using "inject" and starting with one # responsible to append the values. # result = [] arg.map!{|ary| Backports.coerce_to_ary(ary)} arg.reverse! # to get the results in the same order as in MRI, vary the last argument first arg.push self outer_lambda = arg.inject(result.method(:push)) do |proc, values| lambda do |partial| values.each do |val| proc.call(partial.dup << val) end end end outer_lambda.call([]) result end
# File lib/backports/1.9.2/array.rb, line 9 def product_with_block(*arg, &block) return product_without_block(*arg) unless block_given? # Same implementation as 1.8.7, but yielding arg.map!{|ary| Backports.coerce_to_ary(ary)} arg.reverse! # to get the results in the same order as in MRI, vary the last argument first arg.push self outer_lambda = arg.inject(block) do |proc, values| lambda do |partial| values.each do |val| proc.call(partial.dup << val) end end end outer_lambda.call([]) self end
Helper to recurse through flattening Adapted from rubinius'; recursion guards are not needed because level is finite
# File lib/backports/1.8.7/array.rb, line 63 def recursively_flatten_finite(array, out, level) ret = nil if level <= 0 out.concat(array) else array.each do |o| if o.respond_to? :to_ary recursively_flatten_finite(o.to_ary, out, level - 1) ret = self else out << o end end end ret end
Note: Combinations are not yielded in the same order as MRI. This is not a bug; the spec states that the order is implementation dependent
# File lib/backports/1.9.2/array.rb, line 32 def repeated_combination(num) return to_enum(:repeated_combination, num) unless block_given? num = Backports.coerce_to_int(num) if num <= 0 yield [] if num == 0 else indices = Array.new(num, 0) indices[-1] = size while dec = indices.find_index(&:nonzero?) indices[0..dec] = Array.new dec+1, indices[dec]-1 yield values_at(*indices) end end self end
Note: Permutations are not yielded in the same order as MRI. This is not a bug; the spec states that the order is implementation dependent
# File lib/backports/1.9.2/array.rb, line 50 def repeated_permutation(num) return to_enum(:repeated_permutation, num) unless block_given? num = Backports.coerce_to_int(num) if num <= 0 yield [] if num == 0 else indices = Array.new(num, 0) indices[-1] = size while dec = indices.find_index(&:nonzero?) indices[0...dec] = Array.new dec, size-1 indices[dec] -= 1 yield values_at(*indices) end end self end
# File lib/backports/1.8.7/array.rb, line 158 def rindex_with_block(*arg) return rindex_without_block(*arg) unless block_given? && arg.empty? reverse_each.each_with_index{|o,i| return size - 1 - i if yield o} return nil end
# File lib/backports/1.9.2/array.rb, line 67 def rotate(n=1) Array.new(self).rotate!(n) end
# File lib/backports/1.9.2/array.rb, line 71 def rotate!(n=1) n = Backports.coerce_to_int(n) % (empty? ? 1 : size) concat(shift(n)) end
Standard in Ruby 1.8.7+. See official documentation Note: was named choice in 1.8.7 and renamed in later versions
# File lib/backports/1.8.7/array.rb, line 168 def sample(n = Backports::Undefined) return self[Kernel.rand(size)] if n == Backports::Undefined n = Backports.coerce_to_int(n) raise ArgumentError, "negative array size" if n < 0 n = size if n > size result = Array.new(self) n.times do |i| r = i + Kernel.rand(size - i) result[i], result[r] = result[r], result[i] end result[n..size] = [] result end
# File lib/backports/1.9.2/array.rb, line 76 def select! return to_enum(:select!) unless block_given? reject!{|elem| ! yield elem} end
# File lib/backports/1.8.7/array.rb, line 184 def shift_with_optional_argument(n = Backports::Undefined) return shift_without_optional_argument if n == Backports::Undefined n = Backports.coerce_to_int(n) raise ArgumentError, "negative array size" if n < 0 slice!(0, n) end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 194 def shuffle dup.shuffle! end
Standard in Ruby 1.8.7+. See official documentation
# File lib/backports/1.8.7/array.rb, line 199 def shuffle! raise TypeError, "can't modify frozen array" if frozen? size.times do |i| r = i + Kernel.rand(size - i) self[i], self[r] = self[r], self[i] end self end
# File lib/backports/1.9.2/array.rb, line 81 def sort_by! return to_enum(:sort_by!) unless block_given? raise "can't modify frozen array" if frozen? replace sort_by{|e| yield e} end
# File lib/backports/1.9.2/array.rb, line 98 def uniq_with_block return uniq_without_block unless block_given? h = {} each do |elem| h[yield(elem)] ||= elem end h.values end
# File lib/backports/1.9.2/array.rb, line 88 def uniq_with_block! return uniq_without_block! unless block_given? replace self if frozen? # force error u = uniq{|e| yield e} replace u unless u.size == size end