在Ruby中递归地展平数组[重复]
Posted
技术标签:
【中文标题】在Ruby中递归地展平数组[重复]【英文标题】:Flattening an array recursively in Ruby [duplicate] 【发布时间】:2017-05-15 11:45:57 【问题描述】:我很难理解为什么这段代码有效:
def flatten(array, result = [])
array.each do |element|
if element.is_a? Array
flatten(element, result)
else
result << element
end
end
result
end
特别是为什么不用将 flatten 方法调用的结果分配给结果数组就可以工作,像这样:
def flatten1(array, result = [])
array.each do |element|
if element.is_a? Array
result = flatten(element, result)
else
result << element
end
end
result
end
两者产生相同的输出:
p flatten [1,2,[3,4,[5,[6]]]] # [1, 2, 3, 4, 5, 6]
p flatten1 [1,2,[3,4,[5,[6]]]] # [1, 2, 3, 4, 5, 6]
【问题讨论】:
Here's a longer discussion 网站上可能还有更多,但简短的回答是,将Array result
传递给函数是传递实际对象,而不是它的副本,并且对象是由函数内的result << element
修改,因此当递归传递时,它会不断修改而无需重新分配
【参考方案1】:
flatten
方法在第 6 行破坏性地修改了它的第二个参数 result
,并将修改后的数组作为参数传递给第 4 行的递归调用。不需要从该方法返回任何内容,因为无论您传递什么数组因为第二个元素将被破坏性地修改以附加输入数组的扁平版本:
my_array = [:foo]
flatten([1, [2, [3, [4]]]], my_array)
my_array
#=> [:foo, 1, 2, 3, 4]
通常认为修改作为参数传递的对象或通过修改输入参数而不是仅仅返回它来返回值的形式是不好的。看起来代码是由 C 程序员编写的,他想将第二个参数用作输出缓冲区。
更惯用的 Ruby 版本看起来像这样:
def flatten(array)
array.each_with_object([]) do |element, result|
if element.is_a?(Array)
result.concat(flatten(element))
else
result << element
end
end
end
或完全没有突变的纯功能版本:
def flatten(array)
array.inject([]) do |result, element|
result + if element.is_a?(Array)
flatten(element)
else
[element]
end
end
end
【讨论】:
以上是关于在Ruby中递归地展平数组[重复]的主要内容,如果未能解决你的问题,请参考以下文章