在Ruby中以递归方式将嵌套数组展平为点分隔字符串的最有效方法?

时间:2010-08-30 18:31:17

标签: ruby arrays recursion

我想转换这样的内容:

class NestedItem
  attr_accessor :key, :children
  def initialize(key, &block)
    self.key = key
    self.children = []
    self.instance_eval(&block) if block_given?
  end

  def keys
    [key] + children.keys
  end
end

root = NestedItem.new("root") do
  children << NestedItem.new("parent_a") do
    children << NestedItem.new("child_a")
    children << NestedItem.new("child_c")
  end
  children << NestedItem.new("parent_b") do
    children << NestedItem.new("child_y")
    children << NestedItem.new("child_z")
  end
end

require 'pp'
pp root
#=>
# #<NestedItem:0x1298a0
#  @children=
#   [#<NestedItem:0x129814
#     @children=
#      [#<NestedItem:0x129788 @children=[], @key="child_a">,
#       #<NestedItem:0x12974c @children=[], @key="child_c">],
#     @key="parent_a">,
#    #<NestedItem:0x129738
#     @children=
#      [#<NestedItem:0x129698 @children=[], @key="child_y">,
#       #<NestedItem:0x12965c @children=[], @key="child_z">],
#     @key="parent_b">],
#  @key="root">

进入这个:

root.keys #=>
[
  "root",
  "root.parent_a",
  "root.parent_a.child_a",
  "root.parent_a.child_c",
  "root.parent_b",
  "root.parent_b.child_y",
  "root.parent_b.child_z",
]

...使用递归方法。

最简单的方法是什么?

更新

我这样做了:

def keys
  [key] + children.map(&:keys).flatten.map do |node|
    "#{key}.#{node}"
  end
end

还有什么更好的吗?

2 个答案:

答案 0 :(得分:2)

Array.flatten会为你效力吗?

self.children.flatten应该返回展平的结果。

答案 1 :(得分:0)

是的,.flatten会产生我认为你真正想要的东西。

但是如果你想要输入你输入的字符串输出,那就可以了:

  def keys x
    here = key
    here = x + '.' + here if x
    [ here ] + children.inject([]) { |m,o| m += o.keys here }
  end

pp root.keys nil

或者,或者将#keys中的最后一行替换为:

([ here ] + children.map { |o| o.keys here }).flatten