lib/rbbt/util/misc/development.rb in rbbt-util-5.11.9 vs lib/rbbt/util/misc/development.rb in rbbt-util-5.12.0

- old
+ new

@@ -1,6 +1,18 @@ module Misc + + def self.string2const(string) + return nil if string.nil? + mod = Kernel + + string.to_s.split('::').each do |str| + mod = mod.const_get str + end + + mod + end + def self.benchmark(repeats = 1, message = nil) require 'benchmark' res = nil begin measure = Benchmark.measure do @@ -89,7 +101,117 @@ Memprof.stop print Memprof.stats end res + end + + def self.do_once(&block) + return nil if $__did_once + $__did_once = true + yield + nil + end + + def self.reset_do_once + $__did_once = false + end + + def self.insist(times = 3, sleep = nil, msg = nil) + if Array === times + sleep_array = times + times = sleep_array.length + sleep = sleep_array.shift + end + try = 0 + begin + yield + rescue + if msg + Log.warn("Insisting after exception: #{$!.message} -- #{msg}") + else + Log.warn("Insisting after exception: #{$!.message}") + end + if sleep and try > 0 + sleep sleep + sleep = sleep_array.shift if sleep_array + else + Thread.pass + end + try += 1 + retry if try < times + raise $! + end + end + + def self.try3times(&block) + insist(3, &block) + end + + # Divides the array into +num+ chunks of the same size by placing one + # element in each chunk iteratively. + def self.divide(array, num) + num = 1 if num == 0 + chunks = [] + num.to_i.times do chunks << [] end + array.each_with_index{|e, i| + c = i % num + chunks[c] << e + } + chunks + end + + # Divides the array into chunks of +num+ same size by placing one + # element in each chunk iteratively. + def self.ordered_divide(array, num) + last = array.length - 1 + chunks = [] + current = 0 + while current <= last + next_current = [last, current + num - 1].min + chunks << array[current..next_current] + current = next_current + 1 + end + chunks + end + + def self.random_sample_in_range(total, size) + p = Set.new + + if size > total / 10 + template = (0..total - 1).to_a + size.times do |i| + pos = (rand * (total - i)).floor + if pos == template.length - 1 + v = template.pop + else + v, n = template[pos], template[-1] + template.pop + template[pos] = n + end + p << v + end + else + size.times do + pos = nil + while pos.nil? + pos = (rand * total).floor + if p.include? pos + pos = nil + end + end + p << pos + end + end + p + end + + def self.sample(ary, size, replacement = false) + if ary.respond_to? :sample + ary.sample size + else + total = ary.length + p = random_sample_in_range(total, size) + ary.values_at *p + end end end