使用转义子句映射归约,用于处理 nils



所以我正在编写一些代码来计算多段旅程中各种公共交通票选项的成本。 这归结为计算每个段(映射)的成本并将它们相加(reduce又名注入),这很简单:

total = journey.map {|segment| compute segment}.reduce(:+)

问题是,有时compute返回nil因为给定工单无法获得该段,然后求和运算会爆炸。 在这种情况下,我想返回该nil,因为单个错误段意味着整个旅程无效。 目前我正在这样做:

fares = journey.map {|segment| compute segment}
total = if fares.include? nil
  nil
else
  fares.reduce(:+)
end

我也可以写成简洁但(恕我直言)可读性较差:

fares = journey.map {|segment| compute segment}
total = fares.reduce{|sum, n| (sum.nil? or n.nil?) ? nil : sum + n}

但一定有更好的方法,对吧...?

我能想到的第一件事是:

journey.map { |s| compute(s) }.reduce(0) do |sum, fee| 
  break nil unless fee
  sum + fee
end

更新:一旦compute返回nil,这将立即返回nil

journey.reduce(0) do |sum, segment|
  fee = compute(segment)
  break nil unless fee
  sum + fee
end

按以下步骤操作:

result = []
journey.take_while { |segment| !(result << compute(segment)).include?(nil) }
total = (result.size == journey.size)  ? result.inject(:+) : nil

您可以使用Array#take_while方法:

将元素传递给块,直到块返回 nil 或 false,然后停止迭代并返回所有先前元素的数组。

最新更新