将数组值求和到一定总数
Sum array values up to a certain total amount
我有一个散列数组(已排序),如下所示:
testArray = [{price: 540, volume: 12},
{price: 590, volume: 18},
{price: 630, volume: 50}]
现在我想计算一定总体积的平均值。假设某人想购买 40 件,他希望以最便宜的方式购买。这意味着平均价格为 (540*12+590*18+630*50)/40 货币单位。
我的第一次尝试如下:
testArray.each do |priceHash|
@priceArray << priceHash.fetch(:price)
@volumeArray << priceHash.fetch(:volume)
end
def calculateMiddlePrice(priceArray, volumeArray, totalAmount)
result = 0
# Here some crazy wild magic happens
(0...volumeArray.count).inject(0) do |r, i|
if (volumeArray[0..i].inject(:+)) < totalAmount
r += volumeArray[i]*priceArray[i]
elsif volumeArray[0..i-1].inject(:+) < totalAmount && volumeArray[0..i].inject(:+) >= totalAmount
theRest = volumeArray[i] - (volumeArray[0..i].inject(:+) - totalAmount)
r += theRest * priceArray[i]
elsif volumeArray[0] > totalAmount
r = totalAmount * priceArray[0]
end
result = r
end
result
end
现在我什至不确定它为什么有效,但它确实有效。然而,在我眼中,这段代码绝对荒谬。
我的第二个想法是在达到总量时削减我的testArray。代码看起来更好
testAmount = 31
def returnIndexForSlice(array, amount)
sum = 0
array.each_index do |index|
p sum += array[index][:volume]
if sum >= amount
return index+1
end
end
end
testArray.slice(0,returnIndexForSlice(testArray, testAmount))
不过,这感觉不太对,"rubyish" 如果您可以这么说的话。我检查了数组 class 的几乎所有方法,并尝试使用 bsearch,但是我想不出一种真正优雅的方法来解决我的问题。
我的想法是这样的:
amountToCheck = 31
array.some_method.with_index {|sum, index| return index if sum >= amountToCheck}
但是有没有这样的方法或者其他方法呢?
鉴于您的价格哈希数组:
prices = [ {price: 540, volume: 12},
{price: 590, volume: 18},
{price: 630, volume: 50}]
您可以通过 2 个步骤计算出您的结果。
def calc_price(prices, amount)
order = prices.flat_map{|item| [item[:price]] * item[:volume] } #step 1
order.first(amount).reduce(:+)/amount #step 2
end
第 1 步:创建一个数组,其中包含每个单独的项目(如果价格未排序,则必须添加 sort_by
子句)。换句话说,将价格展开为包含 12 个 540、18 590 等的数值数组。这里使用 Ruby 的数组重复方法:[n] * 3 = [n, n, n]
.
第 2 步:平均前 n 个元素
结果:
calc_price(prices, 40)
=> 585
我有一个散列数组(已排序),如下所示:
testArray = [{price: 540, volume: 12},
{price: 590, volume: 18},
{price: 630, volume: 50}]
现在我想计算一定总体积的平均值。假设某人想购买 40 件,他希望以最便宜的方式购买。这意味着平均价格为 (540*12+590*18+630*50)/40 货币单位。
我的第一次尝试如下:
testArray.each do |priceHash|
@priceArray << priceHash.fetch(:price)
@volumeArray << priceHash.fetch(:volume)
end
def calculateMiddlePrice(priceArray, volumeArray, totalAmount)
result = 0
# Here some crazy wild magic happens
(0...volumeArray.count).inject(0) do |r, i|
if (volumeArray[0..i].inject(:+)) < totalAmount
r += volumeArray[i]*priceArray[i]
elsif volumeArray[0..i-1].inject(:+) < totalAmount && volumeArray[0..i].inject(:+) >= totalAmount
theRest = volumeArray[i] - (volumeArray[0..i].inject(:+) - totalAmount)
r += theRest * priceArray[i]
elsif volumeArray[0] > totalAmount
r = totalAmount * priceArray[0]
end
result = r
end
result
end
现在我什至不确定它为什么有效,但它确实有效。然而,在我眼中,这段代码绝对荒谬。
我的第二个想法是在达到总量时削减我的testArray。代码看起来更好
testAmount = 31
def returnIndexForSlice(array, amount)
sum = 0
array.each_index do |index|
p sum += array[index][:volume]
if sum >= amount
return index+1
end
end
end
testArray.slice(0,returnIndexForSlice(testArray, testAmount))
不过,这感觉不太对,"rubyish" 如果您可以这么说的话。我检查了数组 class 的几乎所有方法,并尝试使用 bsearch,但是我想不出一种真正优雅的方法来解决我的问题。
我的想法是这样的:
amountToCheck = 31
array.some_method.with_index {|sum, index| return index if sum >= amountToCheck}
但是有没有这样的方法或者其他方法呢?
鉴于您的价格哈希数组:
prices = [ {price: 540, volume: 12},
{price: 590, volume: 18},
{price: 630, volume: 50}]
您可以通过 2 个步骤计算出您的结果。
def calc_price(prices, amount)
order = prices.flat_map{|item| [item[:price]] * item[:volume] } #step 1
order.first(amount).reduce(:+)/amount #step 2
end
第 1 步:创建一个数组,其中包含每个单独的项目(如果价格未排序,则必须添加 sort_by
子句)。换句话说,将价格展开为包含 12 个 540、18 590 等的数值数组。这里使用 Ruby 的数组重复方法:[n] * 3 = [n, n, n]
.
第 2 步:平均前 n 个元素
结果:
calc_price(prices, 40)
=> 585