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

发布于 2024-09-16 17:43:06 字数 1565 浏览 6 评论 0原文

我想将这样的内容转换

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

还有更好的吗?

I want to convert something like this:

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">

Into this:

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",
]

...using a recursive method.

What's the simplest way to go about this?

Update

I did this:

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

Anything better?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

遥远的她 2024-09-23 17:43:06

Array.flatten 适合你吗?

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

Would Array.flatten work for you?

self.children.flatten should return the flattened results.

窗影残 2024-09-23 17:43:06

是的, .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

Yes, .flatten will produce what I think you really want.

But if you want exactly the string output you typed, this will do it:

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

pp root.keys nil

Or, alternatively, replace the last line in #keys with:

([ here ] + children.map { |o| o.keys here }).flatten
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文