0

このテキスト文字列をハッシュに変換して、ユーザーの入力に基づいてページを作成したいと考えています。

Home
About
- News
-- Local News
-- Global News
- Who We Are
Product

これは単なる例ですが、これを繰り返し処理できる多次元ハッシュに変換したいと思います。ユーザーが CMS で簡単にページを作成できるようにしたいと考えています。

文字列と正規表現を分割して遊んでみましたが、うまくいきませんでした。

どんな助けでも大歓迎です!

4

4 に答える 4

2

Yaml があなたの友達になりそうです。Yaml.load を見てください。test.yml:

"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}}
于 2013-01-11T15:21:41.423 に答える
0

これが私の試みです。私はそれが慣用的に見えないことを十分に認めており、これを置き換えることができるルビー標準ライブラリにワンライナーがあるかもしれません。しかし、少なくともこれは機能します:)

したがって、基本的な考え方は次のとおりです。

  • テキストを分割して行を区切る
  • この行配列を反復し、徐々にハッシュを構築します。これを行っている間、「現在のノード」を追跡し続けます
  • この行に前の行よりも多くの「-」文字が含まれている場合、この行は前の行の子である必要があります
  • 等々

コード:

txt = <<-TXT
Home
About
- News
-- Local News
-- Global News
- Who We Are
Product
TXT

def lines_to_hash lines
  res = {}
  last_level = 0
  parent_stack = [res]
  last_line = nil

  lines.each do |line|
    cur_level = line.scan('-').length
    if cur_level > last_level
      parent_stack << parent_stack.last[last_line]
    elsif cur_level < last_level
      parent_stack.pop
    end

    clean_line = line.gsub(/^[-\s]+/, '')
    parent_stack.last[clean_line] = {}
    last_line = clean_line
    last_level = cur_level
  end
  res
end

res = lines_to_hash(txt.split("\n"))
res # => {"Home"=>{}, 
    #     "About"=>{"News"=>{"Local News"=>{}, "Global News"=>{}}, 
    #               "Who We Are"=>{}}, 
    #     "Product"=>{}}

誰かがワンライナーを思いついたら、賞金で+100担当者を授与します:)

于 2013-01-11T15:12:28.633 に答える
0
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" => {}
# }
于 2013-01-11T16:04:13.553 に答える
0

@Sergio: ここにワンライナーがあります! (確かに、「明確にする」ためにいくつかの行に分割しました)

@ lt-matt8: 実際にこれを使用する場合、後でコードを読みに来る人の正気については責任を負いません :)

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"=>{}}
于 2013-01-11T16:54:39.623 に答える