如何将Ruby reduce方法默认值设为数组首个计算结果而非首元素值
Ruby 选股算法省略reduce负无穷初始值的实现方案
你想要省略reduce方法的负无穷初始值是完全可以实现的,核心思路是先把所有可交易场景的利润统一计算出来,再直接取最大值,完全不需要手动设置聚合初始值。
额外提示:你原有代码存在隐藏bug:用
price_list.index(buy_price)获取买入索引的写法,在数组存在重复价格时会返回第一个匹配价格的索引,会导致卖出日期范围计算错误。比如数组[2,1,1,5]中第二个1的索引本应为2,但index(1)会返回1,最终会把买入日当天的价格也纳入卖出范围,不符合选股规则,以下方案同步修复了该问题。
最优实现(无需手动设置reduce初始值)
def stock_picker(price_list) # 遍历所有合法买入日期(排除最后一天),同步记录索引避免重复价格问题 all_profits = price_list[0..-2].each_with_index.map do |buy_price, buy_idx| # 仅计算买入日期之后的卖出利润,取该买入点的最大利润 price_list[buy_idx+1..].map { |sell_price| sell_price - buy_price }.max end # 直接取所有利润的最大值,自动处理全下跌场景 all_profits.max end # 测试用例,返回18符合预期 b = stock_picker([137,3,6,9,15,8,6,1,10,19,-4]) print(b)
方案说明
- 没有用
reduce做聚合,而是先通过map把所有合法交易的最大利润统一生成一个利润数组,再调用数组自带的max方法取最大值,完全不需要手动设置初始值,天然兼容股价持续下跌的场景,会正确返回亏损最少的利润值。 - 用
each_with_index遍历买入价,直接获取买入索引,解决了重复价格下索引计算错误的问题。
保留reduce写法的实现
如果你还是想要用reduce实现,也可以将第一个买入点的利润作为初始值传入,后续从第二个买入点开始迭代即可,不需要手动写负无穷:
def stock_picker(price_list) buy_dates = price_list[0..-2] # 计算第一个买入点的最大利润作为reduce初始值 initial_profit = price_list[1..].map { |s| s - buy_dates[0] }.max # 从第二个买入点开始迭代聚合 buy_dates[1..].each_with_index.reduce(initial_profit) do |max_profit, (buy_price, offset)| current_max = price_list[offset + 2..].map { |s| s - buy_price }.max [max_profit, current_max].max end end
内容的提问来源于stack exchange,提问作者akayuyang
相关产品推荐
相关产品推荐

