Ruby代码切割(尽可能少行)

时间:2016-10-26 00:17:58

标签: ruby optimization

所以下面的代码是我试图减少尽可能少的行。还有其他任何红宝石技巧可以缩短它吗?我感谢任何人都可以提供的帮助。

文章类:

class Article
    attr_accessor :id, :price, :quantity
    def  initialize(id, price, quantity)
        @id, @price, @quantity = id, Float(price), quantity.to_i
    end 
end

订单类:

class Order
    def initialize(name)
        @a, i = [], 0
        input = File.open(name, "r")
        while(id = input.gets.chomp)
            j, price = 0, input.gets.chomp
            while(j<@a.length)
                if(@a[j].id.eql?(id.to_i))
                    @a[j].quantity += 1     
                end 
            end
            else
                @a[i] = new Article(id,price,1)
                i+=1
            end 
         end 
     end

    def orderCost
        sum = 0
        @a.each { |e| sum+=(e.price * e.quantity)}
        sum = ((sum*1.07) + 2.99)
    end

    def displaySelectArticles
        min, max = @a[0], @a[0]
        @a.each do |e|
            if(min.cost > e.cost)
                min = e
            end
            if(max.cost < e.cost)
                max = e
            end
            sum += e.cost*e.quantity and q += e.quantity
        end
        puts "Min: #{min.cost} | Max: #{max.cost} | Avg: #{Float(sum)/q}"
    end 
end

2 个答案:

答案 0 :(得分:0)

我尽力而为,但你的初始化方法对我来说没有任何合理意义。希望这至少可以引导您走向正确的方向。 免责声明:这些都没有经过测试,而且我用我记得的方法写下了它。

class Order
def initialize(name)
    @a, i = [], 0
    File.readlines(name) do |line|
        # This while loop makes no sense to me
        # Seems like a surefire infiniteloop because if id = 3, it is always true
        # Maybe you meant to do an operator like == for comparison
        while(id = line)
            j, price = 0, line
            while j < @a.length
                @a[j].quantity += 1  if(@a[j].id.eql?(id.to_i))
            end
        else
            @a[i] = new Article(id, price, 1)
            i += 1
        end 
    end 
end

def orderCost
    # I would probably make this two lines because its unreadable
    (@a.inject(0) { |accum, e| accum + (e.price * e.quantity) } * 1.07) + 2.99
end

def displaySelectArticles
    min, max = @a[0], @a[0]
    @a.each do |e|
        min = e if min.cost > e.cost
        max = e if max.cost < e.cost
        sum += e.cost * e.quantity
        q += e.quantity # I have no idea how you got a q
    end
    puts "Min: #{min.cost} | Max: #{max.cost} | Avg: #{Float(sum)/q}"
end 
end

答案 1 :(得分:-1)

文章类需要认真关注,因为那里有混乱的垃圾 三个变量同时分配。把它分成三个非常 简单的任务:

class Article
  attr_accessor :id, :price, :quantity

  def  initialize(id, price, quantity)
    @id = id
    @price = price.to_f
    @quantity = quantity.to_i
  end 
end

使用x.to_f优于Float(x),这是一种更温和的方法 转换。如果您正在进行财务计算,我强烈鼓励 你可以用BigDecimal之类的东西 因为浮点数是众所周知的问题。 1.99美元有办法 成为$ 1.989999423489,在四舍五入时可能会“失去”一分钱 或者那里。 BigDecimal类通过将值表示为精确来避免这种情况。

其余的基本上是在解决不使用Enumerable的问题 有效地,而是编写自己的例程来做简单的事情:

class Order
  def initialize(name)
    @items = [ ]

    File.open(name, "r") do |input|
      while(id = input.gets.chomp)
        price = input.gets.chomp

        # find locates the first matching thing in the array, if any.
        existing = @items.find do |item|
          item.id == id
        end

        if (existing)
          existing.quantity += 1
        else
          items << Article.new(id, price, 1)
        end
     end 
  end

  def item_cost
    # Inject is good at iterating and accumulating
    @items.inject(0.0) do |sum, item|
      sum + item.price * item.quantity
    end
  end

  def item_count
    @items.inject(0) do |sum, item|
      sum + item.quantity
    end
  end

  def order_cost
    item_cost * 1.07 + 2.99
  end

  def display_select_articles
    # minmax_by finds min and max entries based on arbitrary criteria
    min, max = @items.minmax_by { |item| item.price }

    sum = item_cost
    count = item_count

    puts "Min: %f | Max: %f | Avg: %f" % [
      min ? min.cost : 0.0,
      max ? max.cost : 0.0,
      count > 0.0 ? (sum / count) : 0.0
    ]
  end 
end

尽可能使用谷物,这意味着使用Ruby的结构及其原生方法。你偏离这个越多,你需要编写的代码就越多,你的代码就会变得越丑。有时你正在解决一个棘手的问题而你别无选择,但这个例子不是其中之一。如果你只是用Ruby方式做的话,这里的一切都比较简单。