繁体   English   中英

Ruby - 给定一个嵌套数组 arrays,如何仅比较每个嵌套数组的最后一个值来找到最大值?

[英]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}

我们现在可以严格消除79之间的所有天数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 ,这个解决方案被认为是次优的。 我们现在可以严格消除17之间的所有天数d

arr[d] <= arr[7]

其中没有。 我们接下来考虑

days = [ 0, 1,  2, 3, 4,  5,  6]

并在第 6 天卖出。由于之前的最佳买入日期是1 ,这显然是26之间所有卖出日期的最佳买入日期。

我们看到在第6天卖出时的最佳解决方案是

{ buy_day: 1, sell_day: 6, net: 8 }

这又是次优的。 我们现在可以严格消除16之间的所有天数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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM