在 Ruby 中使用每个和多个 if 语句
Using each and multiple if statements in Ruby
我首先要道歉,因为我不确定它是否完全有意义,但我想为您提供尽可能多的背景信息。我正在上一堂课,试图教我迭代哈希和嵌套哈希。我已经为此工作了几天,一直在苦苦挣扎,现在我想我输入了太多行代码,看起来有点草率。
因此首先针对以下项目和测试对该方法进行测试:
describe "Grocer" do
let(:items) do
[
{"AVOCADO" => {:price => 3.00, :clearance => true}},
{"KALE" => {:price => 3.00, :clearance => false}},
{"BLACK_BEANS" => {:price => 2.50, :clearance => false}},
{"ALMONDS" => {:price => 9.00, :clearance => false}},
{"TEMPEH" => {:price => 3.00, :clearance => true}},
{"CHEESE" => {:price => 6.50, :clearance => false}},
{"BEER" => {:price => 13.00, :clearance => false}},
{"PEANUTBUTTER" => {:price => 3.00, :clearance => true}},
{"BEETS" => {:price => 2.50, :clearance => false}},
{"SOY MILK" => {:price => 4.50, :clearance => true}}
]
end
let(:coupons) do
[
{:item => "AVOCADO", :num => 2, :cost => 5.00},
{:item => "BEER", :num => 2, :cost => 20.00},
{:item => "CHEESE", :num => 3, :cost => 15.00}
]
end
所以这些是他们经历的项目。连同优惠券及其价值。以下是 apply_coupons 将要进行的测试:
describe "#apply_coupons" do
context "base case - with perfect coupon (number of items identical):" do
before(:each) do
@avocado = find_item('AVOCADO')
@avocado_coupon = coupons.find { |coupon| coupon[:item] == "AVOCADO" }
@cart = [@avocado, @avocado]
@consolidated_cart = consolidate_cart(@cart)
@avocado_result = apply_coupons(@consolidated_cart, [@avocado_coupon])
end
it "adds a new key, value pair to the cart hash called 'ITEM NAME W/COUPON'" do
expect(@avocado_result.keys).to include("AVOCADO W/COUPON")
end
it "adds the coupon price to the property hash of couponed item" do
expect(@avocado_result["AVOCADO W/COUPON"][:price]).to eq(2.50)
end
it "adds the count number to the property hash of couponed item" do
expect(@avocado_result["AVOCADO W/COUPON"][:count]).to eq(2)
end
it "removes the number of discounted items from the original item's count" do
expect(@avocado_result["AVOCADO"][:price]).to eq(3.00)
expect(@avocado_result["AVOCADO"][:count]).to eq(0)
end
it "remembers if the item was on clearance" do
expect(@avocado_result["AVOCADO W/COUPON"][:clearance]).to eq(true)
end
end
context "more advanced cases:" do
it "accounts for when there are more items than the coupon allows" do
cheese = find_item('CHEESE')
cart = Array.new(5, cheese)
consolidated_cart = consolidate_cart(cart)
cheese_coupon = find_coupon("CHEESE")
cheese_result = apply_coupons(consolidated_cart, [cheese_coupon])
expect(cheese_result["CHEESE"][:price]).to eq(6.50)
expect(cheese_result["CHEESE"][:count]).to eq(2)
expect(cheese_result["CHEESE W/COUPON"][:price]).to eq(5.00)
expect(cheese_result["CHEESE W/COUPON"][:count]).to eq(3)
expect(cheese_result["CHEESE W/COUPON"][:clearance]).to eq(false)
end
it "doesn't break if the coupon doesn't apply to any items" do
cheese = find_item('CHEESE')
cart = Array.new(2, cheese)
consolidated_cart = consolidate_cart(cart)
irrelevant = apply_coupons(consolidated_cart, [find_coupon("AVOCADO")])
expect(irrelevant["CHEESE"][:price]).to eq(6.50)
expect(irrelevant["CHEESE"][:count]).to eq(2)
expect(irrelevant.keys).to_not include("AVOCADO W/COUPON")
expect(irrelevant.keys).to_not include("AVOCADO")
end
it "can apply multiple coupons" do
avocado = find_item('AVOCADO')
cheese = find_item('CHEESE')
cart = Array.new(4, cheese)
3.times { cart << avocado }
consolidated_cart = consolidate_cart(cart)
coupons = [find_coupon("AVOCADO"), find_coupon("CHEESE")]
multiple_coupons = apply_coupons(consolidated_cart, coupons)
["AVOCADO", "CHEESE"].each { |item| expect(multiple_coupons[item][:count]).to eq(1) }
expect(multiple_coupons["CHEESE"][:price]).to eq(6.50)
expect(multiple_coupons["AVOCADO"][:price]).to eq(3.00)
expect(multiple_coupons["CHEESE W/COUPON"][:price]).to eq(5.00)
expect(multiple_coupons["CHEESE W/COUPON"][:count]).to eq(3)
expect(multiple_coupons["CHEESE W/COUPON"][:clearance]).to eq(false)
expect(multiple_coupons["AVOCADO W/COUPON"][:price]).to eq(2.50)
expect(multiple_coupons["AVOCADO W/COUPON"][:count]).to eq(2)
expect(multiple_coupons["AVOCADO W/COUPON"][:clearance]).to eq(true)
end
it "doesn't break if there is no coupon" do
cheese = items.find { |item| item['CHEESE'] }
cart = [cheese, cheese]
consolidated_cart = consolidate_cart(cart)
no_coupon_result = apply_coupons(consolidated_cart, [])
expect(no_coupon_result["CHEESE"][:price]).to eq(6.50)
expect(no_coupon_result["CHEESE"][:count]).to eq(2)
end
it "can increment coupon count if two are applied" do
avocado = find_item("AVOCADO")
coupon = find_coupon("AVOCADO")
consol_cart = consolidate_cart([avocado, avocado, avocado, avocado, avocado])
two_coupon_result = apply_coupons(consol_cart, [coupon, coupon])
expect(two_coupon_result["AVOCADO"][:count]).to eq(1)
expect(two_coupon_result["AVOCADO W/COUPON"][:price]).to eq(2.50)
expect(two_coupon_result["AVOCADO"][:price]).to eq(3.00)
expect(two_coupon_result["AVOCADO W/COUPON"][:count]).to eq(4)
end
end
end
现在,我的代码到目前为止通过了应用多张优惠券的高级案例,而且
可以申请多张优惠券(失败 - 1)
如果没有优惠券则不会中断(失败 - 2)
如果应用了两个(失败 - 3),可以增加优惠券计数:
def apply_coupons(cart, coupons)
#cart is a hash with 2 keys with a nested hash with 3 values
#coupons is an array with a hash with 3 keys and 3 values
#if coupons[0].values.include?(cart.keys[0]) will find avocado in coupon
#coupons[0].values[0] is AVOCADO in coupon
#cart.keys[0] is AVOCADO in cart
#coupons[0].values[0] + " W/COUPON" creates "AVOCADO W/COUPON"
#coupons[0].values[1] = 2 the number of coupons
#coupons[0].values[2] = 5.0 which is the number off need to be divded by 2(number of coupons)
applyCoupons = {}
coupons.each do |k|
if coupons.include?(" W/COUPON")
applyCoupons[coupons[0].values[0] + " W/COUPON"]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:price] = coupons[0].values[2] / coupons[0].values[1]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:clearance] = cart.values[0].has_value?(true)
applyCoupons[coupons[0].values[0]][:count] += 1
end
if cart.keys[0] == coupons[0].values[0]
applyCoupons[cart.keys[0]] = cart.values[0]
applyCoupons[coupons[0].values[0] + " W/COUPON"] = {}
applyCoupons[coupons[0].values[0] + " W/COUPON"][:price] = coupons[0].values[2] / coupons[0].values[1]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:clearance] = cart.values[0].has_value?(true)
applyCoupons[coupons[0].values[0] + " W/COUPON"][:count] = coupons[0].values[1]
applyCoupons[coupons[0].values[0]][:count] -= coupons[0].values[1]
else
applyCoupons[cart.keys[0]] = cart.values[0]
end
end
applyCoupons
end
我得到的错误:
失败:
1) 杂货商#apply_coupons 更高级的案例:可以申请多张优惠券
Failure/Error: ["AVOCADO", "CHEESE"].each { |item| expect(multiple_coupons[item][:count]).to eq(1)}
NoMethodError:
undefined method `[]' for nil:NilClass
# ./spec/grocer_spec.rb:121:in `block (5 levels) in <top (required)>'
# ./spec/grocer_spec.rb:121:in `each'
# ./spec/grocer_spec.rb:121:in `block (4 levels) in <top (required)>'
这是一个很大的问题,但我正在学习,因此非常感谢您的帮助。也很想学习使我的代码更简单的方法。
def apply_coupons(cart, coupons)
coupons.each do |coupon|
if cart.keys.include?(coupon[:item])
if cart[coupon[:item]][:count] >= coupon[:num]
itemwithCoupon = "#{coupon[:item]} W/COUPON"
if cart[itemwithCoupon]
cart[itemwithCoupon][:count] += coupon[:num]
cart[coupon[:item]][:count] -= coupon[:num]
else
cart[itemwithCoupon] = {}
cart[itemwithCoupon][:price] = (coupon[:cost] / coupon[:num])
cart[itemwithCoupon][:clearance] = cart[coupon[:item]][:clearance]
cart[itemwithCoupon][:count] = coupon[:num]
cart[coupon[:item]][:count] -= coupon[:num]
end
end
end
end
cart
end
我首先要道歉,因为我不确定它是否完全有意义,但我想为您提供尽可能多的背景信息。我正在上一堂课,试图教我迭代哈希和嵌套哈希。我已经为此工作了几天,一直在苦苦挣扎,现在我想我输入了太多行代码,看起来有点草率。
因此首先针对以下项目和测试对该方法进行测试:
describe "Grocer" do
let(:items) do
[
{"AVOCADO" => {:price => 3.00, :clearance => true}},
{"KALE" => {:price => 3.00, :clearance => false}},
{"BLACK_BEANS" => {:price => 2.50, :clearance => false}},
{"ALMONDS" => {:price => 9.00, :clearance => false}},
{"TEMPEH" => {:price => 3.00, :clearance => true}},
{"CHEESE" => {:price => 6.50, :clearance => false}},
{"BEER" => {:price => 13.00, :clearance => false}},
{"PEANUTBUTTER" => {:price => 3.00, :clearance => true}},
{"BEETS" => {:price => 2.50, :clearance => false}},
{"SOY MILK" => {:price => 4.50, :clearance => true}}
]
end
let(:coupons) do
[
{:item => "AVOCADO", :num => 2, :cost => 5.00},
{:item => "BEER", :num => 2, :cost => 20.00},
{:item => "CHEESE", :num => 3, :cost => 15.00}
]
end
所以这些是他们经历的项目。连同优惠券及其价值。以下是 apply_coupons 将要进行的测试:
describe "#apply_coupons" do
context "base case - with perfect coupon (number of items identical):" do
before(:each) do
@avocado = find_item('AVOCADO')
@avocado_coupon = coupons.find { |coupon| coupon[:item] == "AVOCADO" }
@cart = [@avocado, @avocado]
@consolidated_cart = consolidate_cart(@cart)
@avocado_result = apply_coupons(@consolidated_cart, [@avocado_coupon])
end
it "adds a new key, value pair to the cart hash called 'ITEM NAME W/COUPON'" do
expect(@avocado_result.keys).to include("AVOCADO W/COUPON")
end
it "adds the coupon price to the property hash of couponed item" do
expect(@avocado_result["AVOCADO W/COUPON"][:price]).to eq(2.50)
end
it "adds the count number to the property hash of couponed item" do
expect(@avocado_result["AVOCADO W/COUPON"][:count]).to eq(2)
end
it "removes the number of discounted items from the original item's count" do
expect(@avocado_result["AVOCADO"][:price]).to eq(3.00)
expect(@avocado_result["AVOCADO"][:count]).to eq(0)
end
it "remembers if the item was on clearance" do
expect(@avocado_result["AVOCADO W/COUPON"][:clearance]).to eq(true)
end
end
context "more advanced cases:" do
it "accounts for when there are more items than the coupon allows" do
cheese = find_item('CHEESE')
cart = Array.new(5, cheese)
consolidated_cart = consolidate_cart(cart)
cheese_coupon = find_coupon("CHEESE")
cheese_result = apply_coupons(consolidated_cart, [cheese_coupon])
expect(cheese_result["CHEESE"][:price]).to eq(6.50)
expect(cheese_result["CHEESE"][:count]).to eq(2)
expect(cheese_result["CHEESE W/COUPON"][:price]).to eq(5.00)
expect(cheese_result["CHEESE W/COUPON"][:count]).to eq(3)
expect(cheese_result["CHEESE W/COUPON"][:clearance]).to eq(false)
end
it "doesn't break if the coupon doesn't apply to any items" do
cheese = find_item('CHEESE')
cart = Array.new(2, cheese)
consolidated_cart = consolidate_cart(cart)
irrelevant = apply_coupons(consolidated_cart, [find_coupon("AVOCADO")])
expect(irrelevant["CHEESE"][:price]).to eq(6.50)
expect(irrelevant["CHEESE"][:count]).to eq(2)
expect(irrelevant.keys).to_not include("AVOCADO W/COUPON")
expect(irrelevant.keys).to_not include("AVOCADO")
end
it "can apply multiple coupons" do
avocado = find_item('AVOCADO')
cheese = find_item('CHEESE')
cart = Array.new(4, cheese)
3.times { cart << avocado }
consolidated_cart = consolidate_cart(cart)
coupons = [find_coupon("AVOCADO"), find_coupon("CHEESE")]
multiple_coupons = apply_coupons(consolidated_cart, coupons)
["AVOCADO", "CHEESE"].each { |item| expect(multiple_coupons[item][:count]).to eq(1) }
expect(multiple_coupons["CHEESE"][:price]).to eq(6.50)
expect(multiple_coupons["AVOCADO"][:price]).to eq(3.00)
expect(multiple_coupons["CHEESE W/COUPON"][:price]).to eq(5.00)
expect(multiple_coupons["CHEESE W/COUPON"][:count]).to eq(3)
expect(multiple_coupons["CHEESE W/COUPON"][:clearance]).to eq(false)
expect(multiple_coupons["AVOCADO W/COUPON"][:price]).to eq(2.50)
expect(multiple_coupons["AVOCADO W/COUPON"][:count]).to eq(2)
expect(multiple_coupons["AVOCADO W/COUPON"][:clearance]).to eq(true)
end
it "doesn't break if there is no coupon" do
cheese = items.find { |item| item['CHEESE'] }
cart = [cheese, cheese]
consolidated_cart = consolidate_cart(cart)
no_coupon_result = apply_coupons(consolidated_cart, [])
expect(no_coupon_result["CHEESE"][:price]).to eq(6.50)
expect(no_coupon_result["CHEESE"][:count]).to eq(2)
end
it "can increment coupon count if two are applied" do
avocado = find_item("AVOCADO")
coupon = find_coupon("AVOCADO")
consol_cart = consolidate_cart([avocado, avocado, avocado, avocado, avocado])
two_coupon_result = apply_coupons(consol_cart, [coupon, coupon])
expect(two_coupon_result["AVOCADO"][:count]).to eq(1)
expect(two_coupon_result["AVOCADO W/COUPON"][:price]).to eq(2.50)
expect(two_coupon_result["AVOCADO"][:price]).to eq(3.00)
expect(two_coupon_result["AVOCADO W/COUPON"][:count]).to eq(4)
end
end
end
现在,我的代码到目前为止通过了应用多张优惠券的高级案例,而且
可以申请多张优惠券(失败 - 1)
如果没有优惠券则不会中断(失败 - 2)
如果应用了两个(失败 - 3),可以增加优惠券计数:
def apply_coupons(cart, coupons)
#cart is a hash with 2 keys with a nested hash with 3 values
#coupons is an array with a hash with 3 keys and 3 values
#if coupons[0].values.include?(cart.keys[0]) will find avocado in coupon
#coupons[0].values[0] is AVOCADO in coupon
#cart.keys[0] is AVOCADO in cart
#coupons[0].values[0] + " W/COUPON" creates "AVOCADO W/COUPON"
#coupons[0].values[1] = 2 the number of coupons
#coupons[0].values[2] = 5.0 which is the number off need to be divded by 2(number of coupons)
applyCoupons = {}
coupons.each do |k|
if coupons.include?(" W/COUPON")
applyCoupons[coupons[0].values[0] + " W/COUPON"]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:price] = coupons[0].values[2] / coupons[0].values[1]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:clearance] = cart.values[0].has_value?(true)
applyCoupons[coupons[0].values[0]][:count] += 1
end
if cart.keys[0] == coupons[0].values[0]
applyCoupons[cart.keys[0]] = cart.values[0]
applyCoupons[coupons[0].values[0] + " W/COUPON"] = {}
applyCoupons[coupons[0].values[0] + " W/COUPON"][:price] = coupons[0].values[2] / coupons[0].values[1]
applyCoupons[coupons[0].values[0] + " W/COUPON"][:clearance] = cart.values[0].has_value?(true)
applyCoupons[coupons[0].values[0] + " W/COUPON"][:count] = coupons[0].values[1]
applyCoupons[coupons[0].values[0]][:count] -= coupons[0].values[1]
else
applyCoupons[cart.keys[0]] = cart.values[0]
end
end
applyCoupons
end
我得到的错误: 失败:
1) 杂货商#apply_coupons 更高级的案例:可以申请多张优惠券 Failure/Error: ["AVOCADO", "CHEESE"].each { |item| expect(multiple_coupons[item][:count]).to eq(1)}
NoMethodError:
undefined method `[]' for nil:NilClass
# ./spec/grocer_spec.rb:121:in `block (5 levels) in <top (required)>'
# ./spec/grocer_spec.rb:121:in `each'
# ./spec/grocer_spec.rb:121:in `block (4 levels) in <top (required)>'
这是一个很大的问题,但我正在学习,因此非常感谢您的帮助。也很想学习使我的代码更简单的方法。
def apply_coupons(cart, coupons)
coupons.each do |coupon|
if cart.keys.include?(coupon[:item])
if cart[coupon[:item]][:count] >= coupon[:num]
itemwithCoupon = "#{coupon[:item]} W/COUPON"
if cart[itemwithCoupon]
cart[itemwithCoupon][:count] += coupon[:num]
cart[coupon[:item]][:count] -= coupon[:num]
else
cart[itemwithCoupon] = {}
cart[itemwithCoupon][:price] = (coupon[:cost] / coupon[:num])
cart[itemwithCoupon][:clearance] = cart[coupon[:item]][:clearance]
cart[itemwithCoupon][:count] = coupon[:num]
cart[coupon[:item]][:count] -= coupon[:num]
end
end
end
end
cart
end