使用键的值作为同一散列中另一个键的值的一部分
Use value of key as part of value of another key in the same hash
如何在声明时使用一个键的值作为对 Ruby 中同一哈希中另一个键值的操作的一部分?
我的意思是这样的:
purchase = {product: 'phone',
quantity: 5,
price: 120,
total: self.quantity * self.price
}
我认为这会很有用,例如,如果值 quantity
是由外部 API 分配的,其中消耗了有限的查询,所以如果 total
也请求,一个花费两次查询而不是要求 'quantity' 只花费一次查询。
你要求的在哈希声明中是不可能的。您可以这样更改代码:
purchase = {}
purchase[:product] = 'phone'
purchase[:quantity] = 5
purchase[:price] = 120
purchase[:total] = purchase[:quantity] * purchase[:price]
或者只是最后一行:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}
purchase[:total] = purchase[:quantity] * purchase[:price]
或其他稍微减少输入的愚蠢方法:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}.tap{ |h| h[:total] = h[:quantity] * h[:price] }
但是,我建议在这种情况下,您不应将 "denormalized" data 存储在您的散列中。由于 total
取决于数量或价格,如果其中任何一个更改,您的哈希值将无效。
您可以通过在您的哈希上创建一个特殊的 default_proc
来解决这个问题,该哈希在每次请求时即时计算总数:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}
purchase.default_proc = ->(h,k){
h[:quantity]*h[:price] if k==:total
}
p purchase[:total] #=> 600
purchase[:quantity] = 7
p purchase[:total] #=> 840
但是,创建一个 class 或 Struct 来执行此操作会更清楚。结构对您来说代码更少:
Purchase = Struct.new(:product,:quantity,:price) do
def total
quantity * price
end
end
purchase = Purchase.new('phone',5,120)
p purchase.total #=> 600
purchase.quantity = 3
p purchase.total #=> 360
但是,Struct 不允许 (by default) 关键字参数。通过编写自己的 class,您可以按任何顺序提供参数,甚至提供默认值:
class Purchase
attr_reader :product, :price, :quantity
def initialize(product:,price:,quantity:1) # default quantity
@product, @price, @quantity = product, price, quantity
end
def total
price*quantity
end
end
Purchase.new(price:10, product:'shoes').total #=> 10
Purchase.new(product:'shoes', price:10).total #=> 10
Purchase.new(quantity:3, price:10, product:'shoes').total #=> 30
我建议创建一个 Purchase
模型来进行计算:
class Purchase
attr_reader :product, quantity, price
def initialize(attributes = {})
@product = attributes[:product]
@quantity = attributes[:quantity]
@price = attributes[:price]
end
def total
quantity * price
end
def to_h
{
product: product,
quantity: quantity,
price: price,
total: total
}
end
end
然后将您的代码更改为:
purchase = Purchase.new(product: 'phone', quantity: 5, price: 120).to_h
作为奖励:此模型易于理解且易于测试。
如何在声明时使用一个键的值作为对 Ruby 中同一哈希中另一个键值的操作的一部分?
我的意思是这样的:
purchase = {product: 'phone',
quantity: 5,
price: 120,
total: self.quantity * self.price
}
我认为这会很有用,例如,如果值 quantity
是由外部 API 分配的,其中消耗了有限的查询,所以如果 total
也请求,一个花费两次查询而不是要求 'quantity' 只花费一次查询。
你要求的在哈希声明中是不可能的。您可以这样更改代码:
purchase = {}
purchase[:product] = 'phone'
purchase[:quantity] = 5
purchase[:price] = 120
purchase[:total] = purchase[:quantity] * purchase[:price]
或者只是最后一行:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}
purchase[:total] = purchase[:quantity] * purchase[:price]
或其他稍微减少输入的愚蠢方法:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}.tap{ |h| h[:total] = h[:quantity] * h[:price] }
但是,我建议在这种情况下,您不应将 "denormalized" data 存储在您的散列中。由于 total
取决于数量或价格,如果其中任何一个更改,您的哈希值将无效。
您可以通过在您的哈希上创建一个特殊的 default_proc
来解决这个问题,该哈希在每次请求时即时计算总数:
purchase = {
product: 'phone',
quantity: 5,
price: 120
}
purchase.default_proc = ->(h,k){
h[:quantity]*h[:price] if k==:total
}
p purchase[:total] #=> 600
purchase[:quantity] = 7
p purchase[:total] #=> 840
但是,创建一个 class 或 Struct 来执行此操作会更清楚。结构对您来说代码更少:
Purchase = Struct.new(:product,:quantity,:price) do
def total
quantity * price
end
end
purchase = Purchase.new('phone',5,120)
p purchase.total #=> 600
purchase.quantity = 3
p purchase.total #=> 360
但是,Struct 不允许 (by default) 关键字参数。通过编写自己的 class,您可以按任何顺序提供参数,甚至提供默认值:
class Purchase
attr_reader :product, :price, :quantity
def initialize(product:,price:,quantity:1) # default quantity
@product, @price, @quantity = product, price, quantity
end
def total
price*quantity
end
end
Purchase.new(price:10, product:'shoes').total #=> 10
Purchase.new(product:'shoes', price:10).total #=> 10
Purchase.new(quantity:3, price:10, product:'shoes').total #=> 30
我建议创建一个 Purchase
模型来进行计算:
class Purchase
attr_reader :product, quantity, price
def initialize(attributes = {})
@product = attributes[:product]
@quantity = attributes[:quantity]
@price = attributes[:price]
end
def total
quantity * price
end
def to_h
{
product: product,
quantity: quantity,
price: price,
total: total
}
end
end
然后将您的代码更改为:
purchase = Purchase.new(product: 'phone', quantity: 5, price: 120).to_h
作为奖励:此模型易于理解且易于测试。