合并红宝石中的类似哈希?

时间:2009-11-10 20:28:54

标签: ruby hash merge

我已经尝试过,但我不能让它变得不那么丑陋/更像红宝石。似乎必须有一个更好的方法。帮助我学习。

class Df
  attr_accessor :thresh
  attr_reader :dfo

  def initialize
      @dfo    = []
      @df     = '/opt/TWWfsw/bin/gdf'

      case RUBY_PLATFORM
      when /hpux/i
          @fstyp = 'vxfs'
      when /solaris/i
          # fix: need /tmp too
          @fstyp = 'ufs'
      when /linux/i
          @df = '/bin/df'
          @fstyp = 'ext3'
      end
      @dfo  = parsedf
  end
  def parsedf
      ldf = []
      [" "," -i"] .each do |arg|
          fields = %w{device size used avail capp mount}
          fields = %w{device inodes inodesused inodesavail iusep mount} if arg == ' -i'
          ldf.push %x{#{@df} -P -t #{@fstyp}#{arg}}.split(/\n/)[1..-1].collect{|line| Hash[*fields.zip(line.split).flatten]}
      end
      out = []
      # surely there must be an easier way
      ldf[0].each do |x|
          ldf[1].select { |y|
              if y['device'] == x['device']
                  out.push x.merge(y)
              end
          }
      end
      out
  end
end

2 个答案:

答案 0 :(得分:2)

没有测试代码,但这里是:

ARGUMENTS = {
  " "   => %w{size used avail capp mount},
  " -i" => %w{inodes inodesused inodesavail iusep mount}
}

def parsedf
  # Store resulting info in a hash:
  device_info = Hash.new do |h, dev|
    h[dev] = {} # Each value will be a empty hash by default
  end

  ARGUMENTS.each do |arg, fields|
    %x{#{@df} -P -t #{@fstyp}#{arg}}.split(/\n/)[1..-1].each do |line|
      device, *data = line.split
      device_info[device].merge! Hash[fields.zip(data)]
    end
  end
  device_info
end

注意:返回的内容与您的内容略有不同:

{ "/dev/sda5" => {"inodes" => "...", ...},
  "other device" => {...}
}

此外,我假设Hash[key_value_pairs]使用Ruby 1.8.7或更高版本,否则您可以使用Hash[*key_value_pairs.flatten]形式

根据您的需要,您应该考虑将字段从字符串切换为符号;它们是最好的钥匙类型。

答案 1 :(得分:1)

在我的机器中,df调用后的ldf数组会产生以下结果:

irb(main):011:0> ldf
=> [[{"device"=>"/dev/sda5", "size"=>"49399372", "mount"=>"/", "avail"=>"22728988", "used"=>"24161036", "capp"=>"52%"}], [{"device"=>"/dev/sda5", "inodes"=>"3137536", "mount"=>"/", "iusep"=>"13%", "inodesavail"=>"2752040", "inodesused"=>"385496"}]]

合并这种结构最灵活的方法可能就是这样:

irb(main):013:0> ldf.flatten.inject {|a,b| a.merge(b)}
=> {"device"=>"/dev/sda5", "inodes"=>"3137536", "size"=>"49399372", "mount"=>"/", "avail"=>"22728988", "inodesavail"=>"2752040", "iusep"=>"13%", "used"=>"24161036", "capp"=>"52%", "inodesused"=>"385496"}

一些红宝石程序员对这种注射用途不以为然,但我喜欢它,所以你的里程可能会有所不同。

至于帮助使你的代码更像红宝石,我建议你和一些经验丰富的rubyist交谈,你可能知道你的代码,以帮助你以一种遵循良好风格和最佳实践的方式重写它。可能这比在这里为你重写它更可取。

最好的运气!