Как читать и преобразовывать из стандартного ввода текстовых данных в структурированные данные в Ruby? - PullRequest
0 голосов
/ 06 января 2012

Я хочу проанализировать стандартный текст и извлечь объект из структурированного контейнера данных.Я путаюсь каждый раз и, наконец, использую глобальные переменные, ARGF, каждая и split.Как я могу сделать это лучше?Как мне легче писать и читать легче?Или какой драгоценный камень мне помогает?

Ниже приведен один случай моего уродливого кода:

# encoding: utf-8
$DATA = {}
$COUNT = 0

ARGF.each do |line|
  col = line.split(nil).map(&:to_i)
  if col.count == 1
    next
  elsif col.count == 2
    $DATA[$COUNT][:cut_param] << { :cut_order => col[0], :pick_count => col[1] }
  elsif col.count == 3
    $COUNT += 1
    $DATA[$COUNT] = {
      :card_amount  => col[0],
      :cut_count    => col[1],
      :needle_order => col[2],
      :cut_param    => []
    }
  end
end

Ответы [ 2 ]

3 голосов
/ 06 января 2012

То, что у тебя есть, не так уж плохо. Возможно, я бы сделал две вещи

  • использовать оператор case вместо elsif '
  • добавляет массив, вместо того, чтобы использовать хеш с числовым ключом и увеличивать счетчик вручную.

Код:

@data = []

ARGF.each do |line|
  col = line.split.map(&:to_i)
  case col.count
  when 3
    @data << {
      :card_amount  => col[0],
      :cut_count    => col[1],
      :needle_order => col[2],
      :cut_param    => []
    }
  when 2
    @data.last[:cut_param] << { :cut_order => col[0], :pick_count => col[1] }
  end
end
0 голосов
/ 06 января 2012

Как насчет чего-то подобного?Включите модульность и добавьте больше структуры к выводу.(Возможно, вы захотите поместить OrderData в модуль DataParser ...)

# encoding: utf-8

class OrderData < Struct.new(:card_amount, :cut_count, :needle_order, :cut_param)
  # Maybe add functionality if needed (existence checking?)
end

module DataParser
  def parse(lines)
    # Die if we get invalid arguments
    if lines.nil? || lines.length == 0 || !(lines.is_a? Array)
      raise ArgumentError, "DataParser::parse Requires a single Array parameter."
    end

    # Collect up our structured output
    output = []

    # Iterate over the input array structuring each result
    lines.each do |line|
      col = line.split.map(&:to_i)
      if col.count == 1
        next
      elsif col.count == 2
        output.last.cut_param << { :cut_order => col[0], :pick_count => col[1] }
      elsif col.count == 3
        output.push(OrderData.new(
          :card_amount  => col[0],
          :cut_count    => col[1],
          :needle_order => col[2],
          :cut_param    => []
        ))
      end
    end
    # Explictly return the output variable instead of the output of the lines
    # array interation.
    return output
  end
end

# If we're run directly, use the command line input for processing
if __FILE__ == $0
  order_data = DataParser::parse(ARGV)
  puts order_data
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...