объединять похожие хэши в ruby? - PullRequest
0 голосов
/ 10 ноября 2009

Я пробовал и пытался, но я не могу сделать это менее уродливым / более рубиновым. Кажется, должен быть лучший путь. Помоги мне учиться.

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 ]

2 голосов
/ 11 ноября 2009

Не тестировал код, но здесь идет:

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" => {...}
}

Кроме того, я предполагаю Ruby 1.8.7 или лучше для Hash[key_value_pairs], в противном случае вы можете прибегнуть к форме Hash[*key_value_pairs.flatten], которая была у вас

В зависимости от ваших потребностей вы должны рассмотреть возможность переключения полей со строки на символы; это лучший тип ключей.

1 голос
/ 11 ноября 2009

На моей машине ваш массив ldf после вызовов df выдает следующее:

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"}

Некоторые программисты ruby ​​недовольны этим использованием inject, но мне это нравится, поэтому ваш пробег может отличаться.

Что касается того, как сделать ваш код более похожим на ruby, я предлагаю вам поговорить с опытным rubyist, которого вы, возможно, знаете по своему коду, чтобы помочь вам переписать его так, чтобы он следовал хорошим стилем и передовым методам. Возможно, это было бы предпочтительнее, чем просто попросить кого-то переписать это здесь для вас.

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...