从
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)