سلسلة روبي # to_class
-
11-09-2019 - |
سؤال
مأخوذة من أ السابق المشاركة مع بعض التعديلات للرد Sepp2k.تعليق حول مساحات الأسماء، لقد قمت بتنفيذ طريقة السلسلة # To_Class. أشارك في الكود هنا وأعتقد أنه يمكن إعادة صياغته بشكل خاص خصيصا "أنا" عداد. تعليقاتك موضع تقدير.
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)
نصائح أخرى
سألقي نظرة على ActiveSupport::CoreExtensions::String::Inflections
على وجه التحديد constantize
طريقة:
def constantize(camel_cased_word)
names = camel_cased_word.split('::')
names.shift if names.empty? || names.first.empty?
constant = Object
names.each do |name|
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
end
constant
end
يمكنك استخدام Recursion:
class String
def to_class(parent = Kernel)
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
end
لا تنتمي إلى StackOverflow