2017-05-25 26 views
1

J'ai 3 classes simples CashRegister, Bill and Position. Un CashRegister est composé d'objets Bill et un objet Bill est composé d'objets Position. Ils sont mis en œuvre comme suitTrouver la fréquence des produits dans cette classe CashRegister

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 

Je veux écrire une méthode de product_frequency qui calcule la fréquence d'un produit acheté dans le CashRegister. Cette méthode retourne un hachage, avec le produit comme clé et la fréquence comme valeur. Un exemple serait:

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} 

Comment puis-je accomplir ce résultat?

+0

Qu'avez-vous essayé jusqu'à présent? Veuillez indiquer votre code. Quel est votre problème? – spickermann

+0

@spickermann Cela vient d'un énorme exercice que j'ai. J'ai essayé de minimiser le problème autant que possible. La réponse de Bartosz fonctionne, mais seulement lorsque la méthode ** positions ** de la classe Bill n'est pas ** protégée **. Y a-t-il moyen d'y parvenir avec des ** positions ** encore ** protégées **? –

Répondre

2

proviennent principalement du solution de Bartosz Bonisławski. Mais puisque positionen dans bill est protected, nous devons d'abord le rendre accessible en définissant une fonction each dans Bill qui prend dans un bloc et l'applique à tous position de positions. Nous faisons également la même chose pour 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 
1

Si vous voulez juste compter combien de fois a été acheté chaque produit, alors voici:

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 

Il est juste une façon de le faire. Code est assez facile, donc je pense que vous pouvez comprendre comment cela fonctionne

+0

Cela fonctionne très bien seulement si la méthode ** positions ** de la classe Bill n'est pas protégée. –

0

Vous pouvez définir #frequency pour chaque classe imbriquée, puis collecter récursivement des hachages.

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