我正在尝试制作一个非常简单的Ruby购物车,如果用户购买某些商品组合,我需要能够提供折扣。这些在@costs中表示 - 如果批量为true,则用户获得折扣(of bulk_price)以进行购买:bulk_num货物。我已经得到了基本费用,但现在我需要在某些情况下减去折扣。这是我到目前为止所做的:
class Cart
attr_accessor :total, :costs, :item_array, :subtotal
def initialize
@item_array=[]
@subtotal=0
@costs= [{"A"=>{:price=>2, :bulk=>true, :bulk_num=>4, :bulk_price=>7}}, {"B"=>{:price=>12, :bulk=> false}},{"C"=>{:price=>1.25,:bulk=>true, :bulk_num=>6, :bulk_price=>6}}, {"D"=>{:price=>0.15, :bulk=>false}}]
end
def scan(*items)
items.each do |item|
@item_array<<item
@costs.each do |cost|
if cost.has_key?(item)
@subtotal+=cost[item][:price]
end
end
@subtotal
end
end
def total
end
end
现在,我已经创建了一个数组来跟踪购买的项目,理想情况下我希望让总函数检查数组,并在需要时从小计中减去。也许我只是盯着这个太久了,但我很难搞清楚。有人可以帮忙吗?
答案 0 :(得分:2)
一些事情:
:total
移除attr_accessor
,不需要它,生成的total
方法将被您稍后定义的方法覆盖。@costs
中查找每个项目的成本。从概念上讲,“购物车”跟踪商店中所有商品的所有价格是没有意义的。total
方法正常运行。不要费心从@subtotal
中减去 - 如果多次调用total
,则会导致问题。实际上,如果您在需要时重新计算,subtotal
也会更好:
def subtotal
@item_array.reduce(0) { |sum,item| sum + (@costs[item][:price] || 0) }
end
现在对你来说可能并不明显,但是像这样“功能性地”编写代码可以更容易地避免错误。您可以缓存值,如果它们的计算成本非常高,并且需要不止一次,但在这种情况下不需要。
对于total
,您可以执行以下操作:
def total
result = self.subtotal
# check which discounts apply and subtract from 'result'
result
end
答案 1 :(得分:1)
由于你的问题涉及练习,我决定稍微改变一下,以便提出一些你可能会觉得有用的观点。几点说明:
scan
重命名为checkout
,以免前者与String#scan checkout
方法的哈希形式为每个订购的商品指定订单数量; :bulk_price
为真且订购的数量至少为:bulk
,我将:bulk_num
更改为适用的单价。@costs
更改为哈希,因为您需要访问项目名称,这些项目现在是密钥。@costs
移到课堂外。首先,这些数据可能会发生变化,因此在课堂定义中确实不应该硬连线。其次,如果您希望不同的类实例使用不同的@costs
,那么这样做可以提供灵活性。在创建新的类实例时,您会看到我选择将该哈希作为参数传递。@costs
中的关键字,则会引发异常。这是我采取的方法:
class Cart
def initialize(costs)
@costs= costs
end
def checkout(items)
purchases = {}
items.each do |(item, qty)|
cost = @costs[item]
raise ArgumentError, "Item '#{item}' not in @costs array" \
if cost == nil
if cost[:bulk] && qty >= cost[:bulk_num]
tot_cost = qty.to_f * cost[:bulk_price]
discount = qty.to_f * (cost[:price] - cost[:bulk_price])
else
tot_cost = qty.to_f * cost[:price]
discount = 0.0
end
purchases[item] = {qty: qty, tot_cost: tot_cost, discount: discount}
end
purchases
end
def tot_cost(purchases)
purchases.values.reduce(0) {|tot, h| tot + h[:tot_cost]}
end
def tot_discount(purchases)
purchases.values.reduce(0) {|tot, h| tot + h[:discount]}
end
end
costs = {"A"=>{price: 2, bulk: true, bulk_num: 4, bulk_price: 1.75},
"B"=>{price: 12, bulk: false },
"C"=>{price: 1.25, bulk: true, bulk_num: 6, bulk_price: 1.00},
"D"=>{price: 0.15, bulk: false }}
cart = Cart.new(costs)
purchases = cart.checkout({"A"=>6, "B"=>7, "C"=>4}) # item => quantity purchased
p purchases # => {"A"=>{:qty=>6, :tot_cost=>10.5, :discount=>1.5},
# => "B"=>{:qty=>7, :tot_cost=>84.0, :discount=>0.0},
# => "C"=>{:qty=>4, :tot_cost=>5.0, :discount=>0.0}}
p cart.tot_cost(purchases) # => 99.5
p cart.tot_discount(purchases) # => 1.5