在此收银机类中查找产品的频率



我有3个简单的类收银机,账单和职位。收银机由账单对象组成,账单对象由头寸对象组成。它们的实现方式如下

class CashRegister
  def initialize
    @bills = []
  end
  def product_frequency
    #???
  end
  def << bill
    @bills << bill
    self
  end
end
class Bill
  attr_reader :positions,:nr
  protected :positions
  def initialize(nr)
    @nr = nr
    @positions = []
  end
  def << pos
    @positions << pos
    self
  end
end
class Position
  attr_reader :product,:quantity,:price
  def initialize(product,quantity,single_price)
    @product = product
    @quantity = quantity
    @price = single_price * quantity
  end
end   

我想编写一个product_frequency方法,用于计算在收银机中购买产品的频率。此方法返回哈希作为结果,乘积作为键,频率作为值。一个例子是:

pos1 = Position.new('Chicken',    5,      12)
pos2 = Position.new('Soup',       6,      24)
pos3 = Position.new('Burger',     3,      19)
pos4 = Position.new('Chicken',    2,      12)
pos5 = Position.new('Soup',       8,      24)
pos6 = Position.new('Burger',     9,      19)
bill1 = Bill.new(1) << pos1 << pos2 << pos3     #Chicken: 5;Soup: 6;Burger: 3
bill2 = Bill.new(2) << pos4 << pos3 << pos2     #Chicken: 2;Soup: 6;Burger: 3
bill3 = Bill.new(3) << pos6 << pos6 << pos6     #Chicken: 0;Soup: 0;Burger: 27
bill4 = Bill.new(4) << pos4 << pos5 << pos4     #Chicken: 4;Soup: 8;Burger: 0
my_cash_register = CashRegister.new << bill1 << bill2 << bill3 << bill4
my_cash_register.product_frequency    #{'Chicken' => 11, 'Soup' => 20, 'Burger' => 33}

我怎样才能实现这个结果?

主要取自Bartosz Bonisławski的解决方案。但是由于bill中的positionenprotected的,我们首先必须通过在Bill中定义一个each函数来使其可访问,该函数接收一个块并将其应用于positions的每个position。我们也为CashRegister做同样的事情。

class CashRegister
  def initialize
    @bills = []
  end
  def each(&block)
    @bills.each(&block)
  end
  def product_frequency
    result = {} 
    each { |bill| 
      bill.each { |position| 
        result[position.product] ||= 0 
        result[position.product] += position.quantity 
      } 
    } 
    result 
  end
  def << bill
    @bills << bill
    self
  end
end
class Bill
  attr_reader :positions,:nr
  protected :positions
  def initialize(nr)
    @nr = nr
    @positions = []
  end
  def each(&block)
    @positions.each(&block)
  end
  def << pos
    @positions << pos
    self
  end
end
class Position
  attr_reader :product,:quantity,:price
  def initialize(product,quantity,single_price)
    @product = product
    @quantity = quantity
    @price = single_price * quantity
  end
end  

如果您只想计算每种产品的购买次数,那么这里是:

  def product_frequency
    product_frequency = {}
    @bills.each do |bill|
      bill.positionen.each do |position|
        @product_frequency[position.product] ||= 0
        @product_frequency[position.product] += position.quantity
      end
    end
    product_frequency
  end

这只是一种方法。代码非常简单,所以我认为你可以弄清楚它是如何工作的

你可以为每个嵌套类定义#frequency,然后递归收集哈希。

class Hash
  def additive_merge!(hash)
    hash.each { |k,v| self[k] ? self[k] += v : self[k] = v }
    self
  end
end
class CashRegister
  def initialize
    @bills = []
  end
  def product_frequency
   @bills.map(&:frequency).reduce(&:additive_merge!)
  end
  def << bill
   @bills << bill
   self
  end
end
class Bill
  attr_reader :positionen,:nr
  protected :positionen
  def initialize(nr)
    @nr = nr
    @positions = []
  end
  def << pos
   @positions << pos
   self
  end
  def frequency
    @positions.map(&:frequency).reduce(&:additive_merge!)
  end
end
class Position
  attr_reader :product,:quantity,:price
  def initialize(product,quantity,single_price)
    @product = product
    @quantity = quantity
    @price = single_price * quantity
  end
  def frequency
    { product => quantity }
  end
end

最新更新