Ruby on rails 将文本解析为多维哈希

Ruby on rails 将文本解析为多维哈希,ruby-on-rails,ruby,Ruby On Rails,Ruby,我想将这个文本字符串转换成散列,以便根据用户输入创建页面 Home About - News -- Local News -- Global News - Who We Are Product 这只是一个例子,但我想把它转换成一个多维散列,我可以迭代。我想为用户创建一个简单的方法,在CMS中创建页面 我已经尝试过拆分字符串和正则表达式,但还没走多远 任何帮助都将不胜感激 这是我的尝试。我完全承认它看起来并不地道,ruby stdlib中可能有一行代码可以取代它。但是,嘿,至少这是有效的:) 因

我想将这个文本字符串转换成散列,以便根据用户输入创建页面

Home
About
- News
-- Local News
-- Global News
- Who We Are
Product
这只是一个例子,但我想把它转换成一个多维散列,我可以迭代。我想为用户创建一个简单的方法,在CMS中创建页面

我已经尝试过拆分字符串和正则表达式,但还没走多远


任何帮助都将不胜感激

这是我的尝试。我完全承认它看起来并不地道,ruby stdlib中可能有一行代码可以取代它。但是,嘿,至少这是有效的:)

因此,基本思想是:

  • 断开文本以分隔行
  • 迭代此行数组并逐步构建哈希。执行此操作时,请继续跟踪“当前节点”
  • 如果此行的“-”字符多于上一行,则此行必须是上一行的子行
  • 等等
代码:

txt={},
#“关于”=>{“新闻”=>{“本地新闻”=>{},“全球新闻”=>{},
#“我们是谁”=>{},
#“产品”=>{}

如果有人提出了一个简单的建议,我将奖励+100代表奖金:)

看起来亚姆会是你的朋友。看看Yaml.load。 test.yml:

"Home":
  "About":
    "News":
      "Local News":
      "Global News":
      "Who We Are":
  "Products":
内部评级

txt={},
#“关于”=>{
#“新闻”=>{
#“本地新闻”=>{},
#“全球新闻”=>{}
#     },
#“我们是谁”=>{}
#   },
#“产品”=>{}
# }

@Sergio:这是一条单行线!(无可否认,为了“清晰起见”,我把它分成了几行)

@lt-matt8:如果你真的使用了这个,那么我对以后来阅读你的代码的人的理智不承担任何责任:)

text={},“关于”=>{“新闻”=>{“本地新闻”=>{},“全球新闻”=>{},“我们是谁”=>{},“产品”=>{}

显示您尝试过的一些代码。什么是多维散列?@sawa它是一种将其他散列作为其值的散列。嵌套哈希是它的另一个术语。你可以在下面的答案中看到例子(方法的输出)@scottelm我知道嵌套哈希,但我不认为它可以称为多维哈希。只想补充:如果你想自己做一个解析器,看看As,如果你想
YAML.load
任何用户可编辑的东西,你都要非常小心!!虽然你的答案在技术上是合格的,@sawa的答案更短。而且他的帖子比较老。无论如何,我得等两天才能开始悬赏。哦,同意了,@sawa的要好得多。我只是试着不用递归就可以做到这一点——如果你必须定义一个方法,从技术上讲,它仍然是一个单行程序吗?;)啊,递归!嗯,我想,从技术上讲,这不是一个单一的班轮。然后你们的版本赢了:)你们是对的。我的是递归的,严格意义上不是一行。不反对塞尔吉奥判给安迪。
"Home":
  "About":
    "News":
      "Local News":
      "Global News":
      "Who We Are":
  "Products":
require 'yaml'
YAML.load(File.open('test.yml'))
=> {"home"=>{"About"=>{"News"=>{"Local News"=>nil, "Global News"=>nil, "Who We Are"=>nil}}, "Product"=>nil}}
txt = <<-TXT
Home
About
- News
-- Local News
-- Global News
- Who We Are
Product
TXT

def hashify s
  Hash[s.split(/^(?!-)\s*(.*)/).drop(1).each_slice(2).map{|k, v| [k, hashify(v.to_s.strip.gsub(/^-/, ""))]}]
end

hashify(txt)
# =>
# {
#   "Home"    => {},
#   "About"   => {
#     "News"       => {
#       "Local News"  => {},
#       "Global News" => {}
#     },
#     "Who We Are" => {}
#   },
#   "Product" => {}
# }
text = <<-TEXT
Home
About
- News
-- Local News
-- Global News
- Who We Are
Product
TEXT

hash = text.lines.each_with_object([{}]) {|item, levels|
  item.match(/(-*)\s*(.*)/).captures.tap {|level, title|
    levels[level.size][title] = (levels[level.size + 1] = {})
  }
}.first
# => {"Home"=>{}, "About"=>{"News"=>{"Local News"=>{}, "Global News"=>{}}, "Who We Are"=>{}}, "Product"=>{}}