我有二维哈希,我想打印出一个简单的html表。存在类似select section,date,count(*) from table group by section,date
的查询,因此某些索引的值可能不存在。
我的ruby代码看起来像
<% sections.each do sec %>
<tr>
<% dates.each do date %>
<% v = 0 %>
<% v = @rws[sec][date] unless @rws.nil? || @rws[sec].nil? || @rws[sec][date].nil? %>
<td><%=v%></td>
<% end %>
</tr>
<% end %>
有没有一种更好的方法可以在没有像do something with a unless a.nil? || a[b].nil? || a[b][c].nil? || a[b][c][d].nil? ...
这样无休止检查的情况下处理多维哈希?
例如,在php中,我只写:
<?php
foreach($sections as $sec)
foreach($dates as $date)
echo "<td>" . ($rws[$sec][$date]?$rws[$sec][$date]:0) . "</td>";
?>
有几种方法可以避免它。我能想到的最简单的方法是替换:
<% v = 0 %>
<% v = @rws[sec][date] unless @rws.nil? || @rws[sec].nil? || @rws[sec][date].nil? %>
<td><%=v%></td>
这个:
<td><%= (@rws[sec][date] rescue nil) || 0 %></td>
意思是:显示哈希的内容。如果它由于某种原因抛出异常(比如调用nil[date](,则返回nil。(nil||0(返回零(我认为这是默认值(。
如果散列只包含数字,您也可以使用:
<td><%= (@rws[sec][date] rescue nil).to_i %></td>
nil.to_i返回零。(不过要注意,"some string".to_i也返回零。(
您可以尝试在控制器内手动将default_proc
连接到@rws
:
@rws = pile_of_stuff_that_produces_a_hash
@rws.default_proc = proc do |h,k|
x = { }
x.default_proc = @rws.default_proc
h[k] = x
x
end
请注意,default_proc
是由新创建的哈希"继承"的(x.default_proc = @rws.default_proc
(,因此您可以一直获得新的哈希。然后,你可以这样做:
@rws[:where][:is][:pancakes][:house?]
它会起作用的。不利的一面是,当你要求一些不存在的东西时,你总是会得到一个空散列,所以你可能不得不在通常会调用nil?
的地方调用emtpy?
。所以你会有这样的东西:
<% dates.each do date %>
<% v = @rws[sec][date] %>
<td><%= v.is_a?(Hash) && v.empty?? 0 : v %></td>
<% end %>
根据您的具体情况,您可能可以将v.is_a?(Hash) && v.empty?
精简为更好的内容;例如,如果@rws
应该一直是数字,那么v.is_a?(Hash)
就足够了。
这种default_proc
方法对于您的特定需求来说可能太聪明了,但一般技术值得一提。
<%= @rws && @rws[sec] && @rws[sec][date] %>
或具有默认值:
<%= (@rws && @rws[sec] && @rws[sec][date]) || 0 %>
这将返回最后一个值。请记住,&&
进行短路求值,在ruby中,只有nil和false求值为false。
只有当中间值始终为零或为散列时,这才有效。。。如果@rws[sec] == "foo"
,则它将给出错误。
在某些情况下,我喜欢default_proc解决方案,尤其是对于深度哈希,但对于小的使用来说,它可能有些过头了。。。
您可以这样做:
<% sections.each do sec %>
<tr>
<% dates.each do date %>
<td><%= @rws[sec][date] rescue 0 %></td>
<% end %>
</tr>
<% end %>