I have a Ruby hash, for example:
我有一个Ruby哈希,例如:
{"monkeys"=> {"hamburgers" => ["love", "eat"],
"boulders" => ["hate", "throw"]},
"stonemasons" => {"boulders" = > ["love", "use"],
"vandals" => ["hate", "sue"]}
}
It can have almost any level (I can put hashes inside hashes any number of times) of depth. It always has arrays as end values.
它几乎可以有任何级别(我可以在任何次数内放入哈希值)深度。它总是将数组作为结束值。
How can I parse it into an HTML table like the one below without using Rails and, preferably, using only the Standard library?
如何在不使用Rails的情况下将其解析为如下所示的HTML表格,最好只使用标准库?
<table>
<tr>
<th rowspan="2">monkeys</th>
<th>hamburgers</th>
<td>love</td>
<td>eat</td>
</tr>
<tr>
<th>boulders</th>
<td>hate</td>
<td>throw</td>
</tr>
<tr>
<th rowspan="2">stonemasons</th>
<th>boulders</th>
<td>love</td>
<td>use</td>
</tr>
<tr>
<th>vandals</th>
<td>hate</td>
<td>sue</td>
</tr>
</table>
1 个解决方案
#1
1
That should do it:
应该这样做:
h = {"monkeys" => {"hamburgers" => ["love", "eat"],
"boulders" => ["hate", "throw"]},
"stonemasons" => {"boulders" => ["love", "use"],
"vandals" => ["hate", "sue"]}}
def parse_data(html, data, new_line = true)
klass = data.class
# Use the class to know if we need to create TH or TD
case
when klass == Hash
data.each do |key, value|
# Start a new row
if new_line
html << '<tr>'
new_line = false
end
# Check if we need to use a rowspan
if value.class == Array || value.count == 1
html << "<th>#{key}</th>"
else
html << "<th rowspan=\"#{value.count}\">#{key}</th>"
end
# Parse the content of the hash (recursive)
html, new_line = parse_data(html, value, new_line)
end
when klass = Array
data.each do |item|
html << "<td>#{item}</td>"
end
# We end the row and flag that we need to start a new one
# if there is anymore data
html << '</tr>'
new_line = true
end
return html, new_line
end
html = '<table>'
html, new_line = parse_data(html, h)
html << '</table>'
puts html
Output:
<table>
<tr>
<th rowspan="2">monkeys</th>
<th>hamburgers</th>
<td>love</td>
<td>eat</td>
</tr>
<tr>
<th>boulders</th>
<td>hate</td>
<td>throw</td>
</tr>
<tr>
<th rowspan="2">stonemasons</th>
<th>boulders</th>
<td>love</td>
<td>use</td>
</tr>
<tr>
<th>vandals</th>
<td>hate</td>
<td>sue</td>
</tr>
</table>
#1
1
That should do it:
应该这样做:
h = {"monkeys" => {"hamburgers" => ["love", "eat"],
"boulders" => ["hate", "throw"]},
"stonemasons" => {"boulders" => ["love", "use"],
"vandals" => ["hate", "sue"]}}
def parse_data(html, data, new_line = true)
klass = data.class
# Use the class to know if we need to create TH or TD
case
when klass == Hash
data.each do |key, value|
# Start a new row
if new_line
html << '<tr>'
new_line = false
end
# Check if we need to use a rowspan
if value.class == Array || value.count == 1
html << "<th>#{key}</th>"
else
html << "<th rowspan=\"#{value.count}\">#{key}</th>"
end
# Parse the content of the hash (recursive)
html, new_line = parse_data(html, value, new_line)
end
when klass = Array
data.each do |item|
html << "<td>#{item}</td>"
end
# We end the row and flag that we need to start a new one
# if there is anymore data
html << '</tr>'
new_line = true
end
return html, new_line
end
html = '<table>'
html, new_line = parse_data(html, h)
html << '</table>'
puts html
Output:
<table>
<tr>
<th rowspan="2">monkeys</th>
<th>hamburgers</th>
<td>love</td>
<td>eat</td>
</tr>
<tr>
<th>boulders</th>
<td>hate</td>
<td>throw</td>
</tr>
<tr>
<th rowspan="2">stonemasons</th>
<th>boulders</th>
<td>love</td>
<td>use</td>
</tr>
<tr>
<th>vandals</th>
<td>hate</td>
<td>sue</td>
</tr>
</table>