简体   繁体   English

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

[英]Ruby - Given an array of nested arrays, how to find the max only comparing the last value of each nested array?

Beginner trying to create a simple stock picker program.初学者尝试创建一个简单的选股程序。 So far my program takes a flat array of integers representing stock prices (indices are days) and returns an array of nested arrays.到目前为止,我的程序采用一个表示股票价格(指数为天)的整数数组,并返回一个嵌套的 arrays 数组。 Each nested array has three values [each consecutive buy day index, best sell day index, profit].每个嵌套数组都有三个值[每个连续买入日指数、最佳卖出日指数、利润]。 Like so:像这样:

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]]

I would like to find the max profit day, then return an array that contains the index values of the buy and sell days of that day.我想找到最大利润日,然后返回一个数组,其中包含当天买卖日的索引值。 In this case it would be:在这种情况下,它将是:

absolute_best = [1, 2]

How do I iterate through an array of nested arrays but only compare the final value of each nested array?如何遍历嵌套的 arrays 数组,但只比较每个嵌套数组的最终值?

To find the largest array element by a condition (here: the value of its 3rd element) you can use max_by in various ways.要按条件查找最大的数组元素(此处:其第三个元素的值),您可以通过多种方式使用max_by

Using array decomposition to extract the 3rd element:使用数组分解提取第三个元素:

best_days.max_by { |a, b, c| c }

# or

best_days.max_by { |_, _, c| c }

# or

best_days.max_by { |*, c| c }

Using the array as is and retrieve its last value:按原样使用数组并检索其last值:

best_days.max_by { |ary| ary.last }

# or

best_days.max_by(&:last)

All of the above return [1, 2, 18] .以上所有返回[1, 2, 18]

In addition to max_by there's also sort_by which can be used to sort the array by profit.除了max_by之外,还有sort_by可用于按利润对数组进行排序。

We can speed up the determination of the desired result as follows.我们可以如下加快确定期望的结果。 Let me explain the procedure with an example that is slightly modified from the one given in the question.让我用一个对问题中给出的例子稍加修改的例子来解释这个过程。 (I changed arr[6] from 8 to 10 .) (我将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]

We first consider selling on the last day, day 9 .我们首先考虑在最后一天,第9天卖出。 Should we do so, the best buy date is如果我们这样做,最好的购买日期是

days.pop
days
  #=>  [ 0, 1,  2, 3, 4,  5,  6, 7,  8]
days.min_by { |d| arr[d] }
  #=> 7 (note arr[7] => 1)

The best pair found so far is given by迄今为止发现的最佳对由下式给出

[7, 9, 14]

or, expressed as a hash,或者,表示为 hash,

{ buy_day: 7, sell_day: 9, net: 14}

We may now eliminate all days d strictly between 7 and 9 for which我们现在可以严格消除79之间的所有天数d

arr[d] <= arr[9]

which is here day 8 .这是第8天。 We are now left with我们现在只剩下

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

We now consider selling on new last day, day 7 .我们现在考虑在新的最后一天,第7天卖出。 The best we can do is given by我们能做的最好的事情是由

{ buy_day: 1, sell_day: 7, net: -1 }

As -1 < 14 , this solution is seen to be sub-optimal.由于-1 < 14 ,这个解决方案被认为是次优的。 We may now eliminate all days d strictly between 1 and 7 for which我们现在可以严格消除17之间的所有天数d

arr[d] <= arr[7]

of which there are none.其中没有。 We next consider我们接下来考虑

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

and selling on day 6. As the previous best buy date was 1 this obviously will be the best buy date for all sell dates between 2 and 6 .并在第 6 天卖出。由于之前的最佳买入日期是1 ,这显然是26之间所有卖出日期的最佳买入日期。

We see that the best solution when selling on day 6 is我们看到在第6天卖出时的最佳解决方案是

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

which again is sub-optimal.这又是次优的。 We may now eliminate all days d strictly between 1 and 6 for which我们现在可以严格消除16之间的所有天数d

arr[d] <= arr[6]

of which there are two, days 3 and 4 .其中有两天, 3天和第4天。 We therefore next consider因此我们接下来考虑

days = [0, 1, 2, 5]

obtaining获得

{ buy_day: 2, sell_day: 5, net: 13 }

which is found to be sub-optimal ( 13 < 14 ).这被发现是次优的( 13 < 14 )。 Day 2 cannot be eliminate (since arr[2] > arr[5] ) so the new problem becomes2天无法消除(因为arr[2] > arr[5] )所以新问题变成

days = [0, 1, 2]

The solution here is这里的解决方案是

{ buy_day: 0, sell_day: 2, net: 18 }

which is found to be the new optimum.发现这是新的最优值。 Lastly,最后,

days = [0, 1]

is considered.被认为。 As作为

days.pop
days = [0]
days.min_by { |d| arr[d] }
  #=> 0

the solution for selling on day 1 is1天卖出的解决方案是

{ buy_day: 0, sell_day: 1, net: -15 }

which is sub-optimal.这是次优的。 The next problem is下一个问题是

days = [0]

Since the array now has only one element we are finished, with the optimal solution being由于数组现在只有一个元素,我们完成了,最优解是

{ buy_day: 0, sell_day: 2, net: 18 }

We can write a method to implement the above approach to computing an optimal buy-sell pair as follows.我们可以编写一个方法来实现上述计算最优买卖对的方法,如下所示。 Note that I have included a puts statement to illustrate the calculations being made.请注意,我包含了一个puts语句来说明正在进行的计算。 That statement should of course be removed.当然应该删除该声明。

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