Ruby 大量使用“函数式概念”中的函数,例如map, each。它们实际上依赖于一个自包含函数,在 Ruby 中称为 block 。
遍历一个二维数组,创建一个关于元素的字符串是很常见的。
在java中,它可能看起来像
public String toString(){
String output = "[";
for (int i =0; i<array.length; i++) {
output+= "Row "+(i+1)+" : ";
for (int j=0; j<array[0].length;j++ ) {
output += array[i][j]+", ";
}
output += "\n";
}
return output += "]";
}
我尝试用“Ruby functional Style”重写这样的东西,但我认为还是有一些改进的地方。例如。我想删除可变变量 output
def to_s
output = "[\n"
@data.each_with_index do |row,i|
output << "Row #{i+1} : "
row.each { |num| output << "#{num}," }
output << "\n"
end
output+"]"
end
最佳答案
每当你看到模式时:
- 初始化一个累加器(在你的例子中是
output
) - 在某些集合的每次迭代中修改累加器(在您的情况下附加到它)
- 归还累加器
那是一个折叠
,或者用 Ruby 的术语来说是一个inject
。
实际上,这有点同义反复。 fold
是一种通用的迭代方法:everything 可以通过迭代集合的元素来表示,也可以表示为 fold
在集合。换句话说:Enumerable
上的所有 方法(包括each
!)也可以根据inject
定义为原始方法而不是 each
。
这样想:一个集合可以是空的,也可以有一个当前元素。没有第三种选择,如果你涵盖了这两种情况,那么你就涵盖了一切。好吧,fold
接受两个参数:一个告诉它当集合为空时要做什么,另一个告诉它如何处理当前元素。或者,换句话说:您可以将集合视为一系列指令,而 fold
是这些指令的解释器。只有两种指令:END
指令和VALUE(el)
指令。您可以为 fold
提供这两条指令的解释器代码。
在 Ruby 中,第二个参数不是参数列表的一部分,而是 block 。
那么,折叠
看起来像什么?
def to_s
@data.each_with_index.inject("[\n") do |acc, (row, i)|
acc + "Row #{i+1} : #{row.join(',')}\n"
end + ']'
end
如果您对 each_with_index
是否会用一些非功能性杂质感染您的代码感到好奇,请放心,您可以通过将索引包含在累加器:
def to_s
@data.inject(["[\n", 1]) do |(s, i), row|
[s + "Row #{i} : #{row.join(',')}\n", i+1]
end.first + ']'
end
另请注意,在第一种情况下,使用 each_with_index
,我们实际上并没有对累加器做任何“有趣”的事情,这与第二种情况不同,我们正在使用它来计算索引。事实上,第一种情况实际上是 fold
的一种限制形式,它并没有使用它的所有功能。它真的只是一个 map
:
def to_s
"[\n" + @data.map.with_index(1) do |row, i|
"Row #{i} : #{row.join(',')}\n"
end.join + ']'
end
在我个人看来,在这里使用(可变的)字符串附加而不是字符串连接实际上是完全可以的:
def to_s
"[\n" << @data.map.with_index(1) do |row, i|
"Row #{i} : #{row.join(',')}\n"
end.join << ']'
end
这使我们免于创建一些不必要的字符串对象,但更重要的是:它更加地道。真正的问题是共享可变状态,但我们并没有在这里共享我们的可变字符串:当to_s
返回时,它的调用者确实获得了对string,但 to_s
本身已经返回,因此无法再访问它。
如果你想要真正的花哨,你甚至可以使用字符串插值:
def to_s
%Q<[\n#{@data.map.with_index(1) do |row, i|
"Row #{i} : #{row.join(',')}\n"
end.join}]>
end
不幸的是,这不仅破坏了 IRb 的语法高亮,而且破坏了我的大脑 ;-)
关于java - 如何循环二维数组中的元素以在 "Ruby functional Style"中构造字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14988918/