使用累加器时,累加器是仅存在于reduce
块内还是存在于函数内?
我的方法如下:
def my_useless_function(str)
crazy_letters = ['a','s','d','f','g','h']
str.split.reduce([]) do |new_array, letter|
for a in 0..crazy_letters.length-1
if letter == crazy_letters[a]
new_array << letter
end
end
end
return true if (new_array == new_array.sort)
end
当我执行此代码时,我收到错误
"undefined variable new_array in line 11 (the return statement)"
我还尝试将new_array
值作为else
块中的reduce
语句分配给另一个变量,但这给了我相同的结果。
有人可以向我解释为什么会这样吗?
答案 0 :(得分:3)
问题是new_array
是在调用reduce
期间创建的,然后引用就会丢失。 Ruby中的局部变量的范围限定在它们所在的块中。在您的情况下,可以从reduce
返回数组,因此您可以在那里使用它。但是,您需要解决一些问题:
str.split
不会将字符串分解为Ruby 2+中的字符。您应该使用str.chars
或str.split('')
。reduce
迭代保留的对象必须通过每次从块返回来保留。最简单的方法是将new_array
作为块中的最后一个表达式。因此:
def my_useless_function(str)
crazy_letters = ['a','s','d','f','g','h']
crazy_only = str.split('').reduce([]) do |new_array, letter|
for a in 0..crazy_letters.length-1
if letter == crazy_letters[a]
new_array << letter
end
end
new_array
end
return true if (crazy_only == crazy_only.sort)
end
请注意,您的功能效率不高,而且不是非常惯用。这是一个较为惯用的功能的较短版本,但效率不高:
def my_useless_function(str)
crazy_letters = %w[a s d f g h]
crazy_only = str.chars.select{ |c| crazy_letters.include?(c) }
crazy_only == crazy_only.sort # evaluates to true or false
end
这是一个效率更高的版本:
def efficient_useless(str)
crazy_only = str.scan(/[asdfgh]/) # use regex to search for the letters you want
crazy_only == crazy_only.sort
end
答案 1 :(得分:2)
new_array
在reduce
来电的阻止之外不存在。它是"block local variable"。
reduce
会返回一个对象,你应该在你的方法中使用它。
sum = [1, 2, 3].reduce(0){ |acc, elem| acc + elem }
puts sum
# 6
puts acc
# undefined local variable or method `acc' for main:Object (NameError)
这是您方法的最小更改量:
def my_useless_function(str)
crazy_letters = ['a','s','d','f','g','h']
new_array = str.split(//).reduce([]) do |new_array, letter|
for a in 0..crazy_letters.length-1
if letter == crazy_letters[a]
new_array << letter
end
end
new_array
end
return true if (new_array == new_array.sort)
end
注意:
return
最后不需要。true if ...
不需要for
循环reduce
返回块内最后一个表达式的结果。您的代码中为for
。reduce
中返回相同的对象,则可能是您可以使用each_with_object
的标志。"test".split
只是["test"]
String和Enumerable有可以帮助您的方法。使用它们,您可以编写更清晰,更有效的方法,如@Phrogz answer。