实现Array#flatten

时间:2017-01-04 08:51:26

标签: arrays ruby

我需要实施Array#flatten。此实现删除所有嵌套数组:

a = [1, 2, [3, [4, 5]]]

def my_flatten(arr)
  arr.reduce([]) do |result, item| 
    item.is_a?(Array) ? result + my_flatten(item) : result << item
  end
end

my_flatten(a) #=> [1, 2, 3, 4, 5]

提示如何实施此类行为

a.flatten(1) #=> [1, 2, 3, [4, 5]]

3 个答案:

答案 0 :(得分:3)

引入一个参数来指定最大深度(默认为nil)和一个跟踪当前深度的参数(初始调用为0,然后在每次递归调用时递增1):

def my_flatten(arr, max_depth = nil, current_depth = 0)
    arr.reduce([]) do |result, item| 
      item.is_a?(Array) && (max_depth.nil? || current_depth < max_depth) ? 
        result + my_flatten(item, max_depth, current_depth + 1) : result << item
    end
end

如果您认为这更具可读性,可以将?:替换为if/else

def my_flatten(arr, max_depth = nil, current_depth = 0)
  arr.reduce([]) do |result, item|
    if item.is_a?(Array) && (max_depth.nil? || current_depth < max_depth)
      result + my_flatten(item, max_depth, current_depth + 1)
    else
      result << item
    end
  end
end

现在返回预期结果:

 my_flatten(a) #=> [1, 2, 3, 4, 5]

 my_flatten(a, 1) #=> [1, 2, 3, [4, 5]]

答案 1 :(得分:2)

我很长一段时间创造了类似的东西。这是gist link

来自要点的代码:

<rule>
    <condition type="scheme" operator="equal">^http$</condition>
    <from>/(.*)</from>
    <set type="status">307</set>
    <set type="response-header" name="Location">https://something.com/$1</set>
    <to last="true">null</to>
</rule>

希望有所帮助。

答案 2 :(得分:1)

你也可以像这样使用Proc

class Array
  def my_flatten(level = nil)
    p = ->(arr, exp, lvl) do
      arr.each { |val| Array === val && (!level || lvl < level) ? p.(val, exp, lvl+1) : exp << val }
      exp
    end

    p.(self, [], 0)
  end
end

a = [1, 2, [3, [4, 5]]]
p a.my_flatten
# => [1, 2, 3, 4, 5]
p a.my_flatten(0)
# => [1, 2, [3, [4, 5]]]
p a.my_flatten(1)
# => [1, 2, 3, [4, 5]]
p a.my_flatten(2)
# => [1, 2, 3, 4, 5]