0

次の入力が与えられた場合 (CSV ファイルから):

input = [
  { :level => 0, :value => "a"   },
  { :level => 1, :value => "1"   },
  { :level => 1, :value => "2"   },
  { :level => 2, :value => "I"   },
  { :level => 2, :value => "II"  },
  { :level => 2, :value => "III" },
  { :level => 0, :value => "b"   },
  { :level => 0, :value => "c"   },
  { :level => 0, :value => "d"   },
  { :level => 1, :value => "3"   },
  { :level => 1, :value => "4"   },
]

「The Ruby Way」でこれを次のように変換するにはどうすればよいですか。

expected = [
  { :value => "a", :children => [ { :value => 1, :children => nil },
                                  { :value => 2, :children => [ { :value => "I", :children => nil },
                                                                { :value => "II", :children => nil },
                                                                { :value => "III", :children => nil } ] } ] },
  { :value => "b", :children => nil },
  { :value => "c", :children => nil },
  { :value => "d", :children => [ { :value => 3, :children => nil },
                                  { :value => 4, :children => nil } ] },
  ]

?

編集:

これに対する私の解決策は、問題を回避し、変換し、他の誰かに解決してもらうことでした:

require 'yaml'
def linear_to_tree(a)
  yaml_lines = []

  a.each do |el|
    indent = " " * 4 * el[:level]
    yaml_lines << "#{indent}-"
    yaml_lines << "#{indent}  :value: #{(el[:value])}"
    yaml_lines << "#{indent}  :children:"
  end
  yaml_lines << ""  # without this, YAML.load complains
  yaml = yaml_lines.join("\n")
  # open("test_yaml.txt", "w"){|f| f.write(yaml)}
  YAML.load(yaml)
end

しかし、これを解決するためのよりエレガントな方法が必要です。

PS 可能かどうかを確認するために、この変換のワンライナーも見たいと思います。

4

1 に答える 1

0

子を持たないノードには空の配列を使用する必要があります。空の配列はコレクションの null オブジェクトです。そうしないと、割り当てるときと使用するときの両方で踊らなければなりません。

def transform(inputs)
  transform! inputs.dup
end

def transform!(inputs, output=[], current_level=0)
  while inputs.any?
    input = inputs.shift
    level, value = input.values_at :level, :value
    value = value.to_i if value =~ /\A\d+\z/
    if level < current_level
      inputs.unshift input
      break
    elsif level == current_level
      next_children = []
      output << {value: value, children: next_children}
      transform! inputs, next_children, current_level.next
    else
      raise "presumably should not have gotten here"
    end
  end
  output
end
于 2013-03-19T00:47:17.333 に答える