Ruby String#to_class

前端之家收集整理的这篇文章主要介绍了Ruby String#to_class前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
previous帖子中做了一些修改以响应 sepp2k关于命名空间的评论,我已经实现了String#to_class方法.我在这里分享代码,我相信它可能会被重构,特别是“i”计数器.您的意见表示赞赏.
class String
   def to_class
     chain = self.split "::"
     i=0
     res = chain.inject(Module) do |ans,obj|
       break if ans.nil?
       i+=1
       klass = ans.const_get(obj)
       # Make sure the current obj is a valid class 
       # Or it's a module but not the last element,# as the last element should be a class
       klass.is_a?(Class) || (klass.is_a?(Module) and i != chain.length) ? klass : nil
     end
   rescue NameError
     nil
   end
 end

 #Tests that should be passed.
 assert_equal(Fixnum,"Fixnum".to_class)
 assert_equal(M::C,"M::C".to_class)
 assert_nil "Math".to_class
 assert_nil "Math::PI".to_class
 assert_nil "Something".to_class

解决方法

我好奇地运行了一些基准测试,我的解决方案很慢!
这是一个带有基准的重构解决方案,希望有所帮助.
require "benchmark"

class String
  def to_class_recursive
    chain = self.split "::"
    klass = parent.const_get chain.shift
    return chain.size < 1 ? (klass.is_a?(Class) ? klass : nil) : chain.join("::").to_class(klass)
  rescue
    nil
  end

  def to_class_original
    chain = self.split "::"
    i=0
    res = chain.inject(Module) do |ans,obj|
      break if ans.nil?
      i+=1
      klass = ans.const_get(obj)
      # Make sure the current obj is a valid class 
      # Or it's a module but not the last element,# as the last element should be a class
      klass.is_a?(Class) || (klass.is_a?(Module) and i != chain.length) ? klass : nil
    end
  rescue NameError
    nil
  end

  def to_class_refactored
    chain = self.split "::"
    klass = Kernel
    chain.each do |klass_string|
      klass = klass.const_get klass_string
    end
    klass.is_a?(Class) ? klass : nil
  rescue NameError
    nil
  end
end

module M
  class C
  end
end

n = 100000
class_string = "M::C"
Benchmark.bm(20) do |x|
  x.report("to_class_recursive") { n.times { class_string.to_class_recursive } }
  x.report("to_class_original") { n.times { class_string.to_class_original } }
  x.report("to_class_refactored") { n.times { class_string.to_class_refactored } }
end

#                           user     system      total        real
# to_class_recursive    2.430000   0.170000   2.600000 (  2.701991)
# to_class_original     1.000000   0.010000   1.010000 (  1.049478)
# to_class_refactored   0.570000   0.000000   0.570000 (  0.587346)
原文链接:https://www.f2er.com/ruby/271260.html

猜你在找的Ruby相关文章