我常常在ruby中加入的一个东西是递归模式。例如,假设我有一个数组,并且可能包含数组作为无限深度的元素。所以,例如:
my_array = [1, [2, 3, [4, 5, [6, 7]]]]
我想创建一个可以将数组展平为[1, 2, 3, 4, 5, 6, 7]
的方法。
我知道.flatten
可以完成这项工作,但这个问题是我经常遇到的递归问题的一个例子 - 因此我试图找到一个更可重用的解决方案。
简而言之 - 我猜这种东西有一个标准模式,但我无法想出任何特别优雅的东西。任何想法赞赏
答案 0 :(得分:5)
递归是一种方法,它不依赖于语言。您在编写算法时考虑了两种情况:再次调用函数的函数(递归情况)和破坏它的函数(基本情况)。例如,在Ruby中进行递归展平:
class Array
def deep_flatten
flat_map do |item|
if item.is_a?(Array)
item.deep_flatten
else
[item]
end
end
end
end
[[[1]], [2, 3], [4, 5, [[6]], 7]].deep_flatten
#=> [1, 2, 3, 4, 5, 6, 7]
这有帮助吗?无论如何,这里显示的有用模式是,当您在数组上使用reusion时,通常需要flat_map
(each
+ concat
/ push
的功能替代。)< / p>
答案 1 :(得分:4)
好吧,如果你知道一点C,你只需要访问文档并单击ruby函数来获取C源代码就可以了。
http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-flatten
对于这种情况,这是一个Ruby实现
def flatten values, level=-1
flat = []
values.each do |value|
if level != 0 && value.kind_of?(Array)
flat.concat(flatten(value, level-1))
else
flat << value
end
end
flat
end
p flatten [1, [2, 3, [4, 5, [6, 7]]]]
#=> [1, 2, 3, 4, 5, 6, 7]
答案 2 :(得分:2)
这是一个以尾递归方式书写的扁平的例子。
class Array
# Monkeypatching the flatten class
def flatten(new_arr = [])
self.each do |el|
if el.is_a?(Array)
el.flatten(new_arr)
else
new_arr << el
end
end
new_arr
end
end
p flatten [1, [2, 3, [4, 5, [6, 7]]]]
#=> [1, 2, 3, 4, 5, 6, 7]
虽然看起来ruby并不总是针对尾递归进行优化:Does ruby perform tail call optimization?