From: Shinya Kawaji Date: 2009-02-26T03:07:25+09:00 Subject: [ruby-list:45891] Re: how to extract nested table かわじ、です。 > 図解. > > | | | "c" | > | "a" | "b" | "ca" | "cb" | "cc" | > --+---------+---------+------+------+------+ > | | |"ca11"|"cb11"|"cc11"| > 1 | "a1" | "b1" |"ca12"|"cb12"|"cc12"| > | | |"ca13"|"cb13"|"cc13"| > --+---------+---------+------+------+------+ > : : : : : : これは具体的には、HTMLではどう書くのでしょう。 2例ほど考えたので後で載せますが、それはともかく、 > [{"a" => "a1", "b" => "b1", > "c" => [{"ca" => "ca11", "cb" => "cb11", "cc" => "cc11"}, > {"ca" => "ca12", "cb" => "cb12", "cc" => "cc12"}, > {"ca" => "ca13", "cb" => "cb13", "cc" => "cc13"}]}, > {"a" => "a2", "b" => "b2", ..... > > のようなデータを引っ張ってくるためにメソッドに構造を知らせるために > 配列を使うと ["a", "b", ["ca", "cb", "cc"]] となり, "c" のような枝 > 部分の見出しを知らせることが出来ません.一方でハッシュを使って構造を > 知らせようとすると, > {"a" => nil, "b" => nil, "c" => {"ca" => nil, "cb" => nil, "cc" => nil}} > といった感じになりましょうが,ハッシュなので順序が確保できません. 「見出し」部分は全て配列の入れ子にして、位置を特定するようにすればいかが でしょう。 # キー部分の配列 keys = ['a', 'b', ['c', ['ca', 'cb', 'cc']]] 別途、データの中身も全て配列の入れ子にして、 # データの中身 vals = [ ['a1', 'b1', [ ['ca11', 'cb11', 'cc11'], ['ca12', 'cb12', 'cc12'], ['ca13', 'cb13', 'cc13'], ]], ] それから最終的に、 def set(table, key, val) if key.kind_of?(Array) and val.kind_of?(Array) table[key.first] = [] val.each_with_index{|row, row_idx| t = table[key.first][row_idx] = {} key.last.each_with_index{|k, key_idx| set(t, k, row[key_idx]) } } elsif key.kind_of?(String) and val.kind_of?(String) table[key] = val else raise ArgumentError, "key: #{key.inspect}, val: #{val.inspect}" end end table = vals.collect{|row| t = {} row.each_with_index{|cell, i| set(t, keys[i], cell) } t } とします。set関数はかなりベタな書き方なので、もっと美しく出来るでしょう。 こういった感じで、解決になるでしょうか。 以下、おまけ。 ■考えたHTML その1
a b
c
ca cb cc
1 a1 b1
ca11 cb11 cc11
ca12 cb12 cc12
ca13 cb13 cc13
■考えたHTML その2
a b c
ca cb cc
1 a1 b1 ca11 cb11 cc11
ca12 cb12 cc12
ca13 cb13 cc13