我定义了一个函数来将字符串转换为int (我知道它已经定义了)。考虑一下,遍历一个字符串到最后一个元素,然后根据它的位置得到指数(它是一个用于说明的函数,没有其他的)。但是,更改累加器的值,如:
def toIntR s
acc = 0 #accumulator
def hack (s, b)
return 0 if s.empty?
x = hack(s[1..-1], b)
eval("acc = acc + #{s[0].to_i*(10**x)}", b)
x+1
end
hack(s, binding) #actual binding
acc
end我想像这样的算法:(更直观)
def toIntI s
acc = 0
l = s.length-1
s.each_char.with_index do |x,i|
acc += x.to_i*(10**(l - i))
end
acc
end那么,哪一个更好?还是更快?还是优雅?还是一个好的做法?
发布于 2015-03-02 13:58:19
首先,我想说我不是Ruby的专家。但我真的,真的想根据我所知道的来分享我对这个问题的看法。
def toIntR s
acc = 0 #accumulator
def hack (s, b)
return 0 if s.empty?
x = hack(s[1..-1], b)
eval("acc = acc + #{s[0].to_i*(10**x)}", b)
x+1
end
hack(s, binding) #actual binding
acc
end在上面的方法中,您使用def定义了另一个方法。这实际上很糟糕,因为在调用方法hack时,它在main上定义了另一个名为toIntR的方法,从而使方法toIntR失去了其本地作用域。我的意思是,你并不希望toIntR方法的本地内容是全局的。在您的上下文中,您希望调用方法toIntR,该方法使用其本地作用域执行它所做的工作,然后将结果返回给您,对吗?
相反,如果您想遵循这种风格,我建议您使用lambda或proc (更喜欢lambda)。
而且在hack方法中,在修改函数的局部作用域之外使用递归的方式并不好,特别是对于eval和使用不同的绑定。最好只返回结果,同时在函数的局部变量中创建和修改结果。它只是简单地增加了它的可重用性和模块化。
这就是我重写的方式:
def toIntR str
hack = ->(str) do
str.empty?? 0 : hack[str.chop] * 10 + str[-1].to_i
end
hack[str]
end哪一个更快,更优雅,有更好的实践?
递归的迭代替代方案总是更快、更高效,尽管它们比递归版本多了几行代码,所以第二个解决方案更快。
第二个是优雅的。它所做的非常简单,而且很简单。没有任何必要的部分,如第一个,使它更快的初学者理解。
第二,也有更好的实践。因为在第一个版本下面没有我说过的话。
发布于 2015-03-02 13:58:28
我肯定会说第二个选择更好。除了调试之外,使用eval几乎总是一个坏主意。它是缓慢的,它是丑陋的,它使代码很难维护。至于优雅,您可能想看看inject模块中的Enumerable方法:
def toIntI(s)
s.each_char.with_index.inject(0) do |acc, (char, i)|
acc + char.to_i * (10**(s.length - i - 1))
end
endhttps://stackoverflow.com/questions/28808921
复制相似问题