[英]Ruby - Given an array of nested arrays, how to find the max only comparing the last value of each nested array?
初学者尝试创建一个简单的选股程序。 到目前为止,我的程序采用一个表示股票价格(指数为天)的整数数组,并返回一个嵌套的 arrays 数组。 每个嵌套数组都有三个值[每个连续买入日指数、最佳卖出日指数、利润]。 像这样:
stock_prices = [17, 2, 20, 6, 9, 15, 8, 1, 15, 15]
best_days = [[ 0, 2, 3], [ 1, 2, 18], [ 2, 5, -5],
[ 3, 5, 9], [ 4, 5, 6], [ 5, 8, 0],
[ 6, 8, 7], [ 7, 8, 14], [ 8, 9, 0]]
我想找到最大利润日,然后返回一个数组,其中包含当天买卖日的索引值。 在这种情况下,它将是:
absolute_best = [1, 2]
如何遍历嵌套的 arrays 数组,但只比较每个嵌套数组的最终值?
要按条件查找最大的数组元素(此处:其第三个元素的值),您可以通过多种方式使用max_by
。
使用数组分解提取第三个元素:
best_days.max_by { |a, b, c| c }
# or
best_days.max_by { |_, _, c| c }
# or
best_days.max_by { |*, c| c }
按原样使用数组并检索其last
值:
best_days.max_by { |ary| ary.last }
# or
best_days.max_by(&:last)
以上所有返回[1, 2, 18]
。
除了max_by
之外,还有sort_by
可用于按利润对数组进行排序。
我们可以如下加快确定期望的结果。 让我用一个对问题中给出的例子稍加修改的例子来解释这个过程。 (我将arr[6]
从8
更改为10
。)
arr = [17, 2, 20, 6, 9, 15, 10, 1, 15, 15]
days = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我们首先考虑在最后一天,第9
天卖出。 如果我们这样做,最好的购买日期是
days.pop
days
#=> [ 0, 1, 2, 3, 4, 5, 6, 7, 8]
days.min_by { |d| arr[d] }
#=> 7 (note arr[7] => 1)
迄今为止发现的最佳对由下式给出
[7, 9, 14]
或者,表示为 hash,
{ buy_day: 7, sell_day: 9, net: 14}
我们现在可以严格消除7
到9
之间的所有天数d
arr[d] <= arr[9]
这是第8
天。 我们现在只剩下
days = [ 0, 1, 2, 3, 4, 5, 6, 7]
我们现在考虑在新的最后一天,第7
天卖出。 我们能做的最好的事情是由
{ buy_day: 1, sell_day: 7, net: -1 }
由于-1 < 14
,这个解决方案被认为是次优的。 我们现在可以严格消除1
到7
之间的所有天数d
arr[d] <= arr[7]
其中没有。 我们接下来考虑
days = [ 0, 1, 2, 3, 4, 5, 6]
并在第 6 天卖出。由于之前的最佳买入日期是1
,这显然是2
到6
之间所有卖出日期的最佳买入日期。
我们看到在第6
天卖出时的最佳解决方案是
{ buy_day: 1, sell_day: 6, net: 8 }
这又是次优的。 我们现在可以严格消除1
到6
之间的所有天数d
arr[d] <= arr[6]
其中有两天, 3
天和第4
天。 因此我们接下来考虑
days = [0, 1, 2, 5]
获得
{ buy_day: 2, sell_day: 5, net: 13 }
这被发现是次优的( 13 < 14
)。 第2
天无法消除(因为arr[2] > arr[5]
)所以新问题变成
days = [0, 1, 2]
这里的解决方案是
{ buy_day: 0, sell_day: 2, net: 18 }
发现这是新的最优值。 最后,
days = [0, 1]
被认为。 作为
days.pop
days = [0]
days.min_by { |d| arr[d] }
#=> 0
第1
天卖出的解决方案是
{ buy_day: 0, sell_day: 1, net: -15 }
这是次优的。 下一个问题是
days = [0]
由于数组现在只有一个元素,我们完成了,最优解是
{ buy_day: 0, sell_day: 2, net: 18 }
我们可以编写一个方法来实现上述计算最优买卖对的方法,如下所示。 请注意,我包含了一个puts
语句来说明正在进行的计算。 当然应该删除该声明。
def doit(arr,
days = arr.size.times.to_a,
sell_day = days.pop,
buy_day = days.min_by { |d| arr[d] },
best = { buy_day: nil, sell_day: nil, net: -Float::INFINITY })
puts "days=#{days}, sell_day=#{sell_day}, buy_day=#{buy_day}, best=#{best}"
return best if days.size == 1
sell_price = arr[sell_day]
candidate = sell_price - arr[buy_day]
best = { buy_day: buy_day, sell_day: sell_day, net: candidate } if
candidate > best[:net]
days.reject! { |d| d > buy_day && arr[d] <= sell_price }
sell_day = days.pop
buy_day = days.min_by { |d| arr[d] } if sell_day <= buy_day
doit(arr, days, sell_day, buy_day, best)
end
arr = [17, 2, 20, 6, 9, 15, 10, 1, 15, 15]
doit(arr)
days=[0, 1, 2, 3, 4, 5, 6, 7, 8], sell_day=9, buy_day=7,
best={:buy_day=>nil, :sell_day=>nil, :net=>-Infinity}
days=[0, 1, 2, 3, 4, 5, 6], sell_day=7, buy_day=1,
best={:buy_day=>7, :sell_day=>9, :net=>14}
days=[0, 1, 2, 3, 4, 5], sell_day=6, buy_day=1,
best={:buy_day=>7, :sell_day=>9, :net=>14}
days=[0, 1, 2], sell_day=5, buy_day=1,
best={:buy_day=>7, :sell_day=>9, :net=>14}
days=[0, 1], sell_day=2, buy_day=1,
best={:buy_day=>7, :sell_day=>9, :net=>14}
days=[0], sell_day=1, buy_day=0,
best={:buy_day=>1, :sell_day=>2, :net=>18}
#=> {:buy_day=>1, :sell_day=>2, :net=>18}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.