5

我想遍历一个数组,它的每个元素都是一个由两个整数组成的数组(例如'[3,5]');对于这些元素中的每一个,我想计算两个整数的总和,当这些总和中的任何一个超过某个任意值时退出循环。源数组非常大,我可能会在开头附近找到所需的值,因此循环遍历所有不需要的元素不是一个好的选择。

我已经编写了三个循环来执行此操作,所有这些都会产生所需的结果。我的问题是:哪个更惯用 Ruby?或者——更好的是——有更好的方法吗?我尽量不要在其中使用非局部循环变量,但break语句在我(诚然是新手)眼中看起来有点骇人听闻。

# Loop A
pairs.each do |pair|
  pair_sum = pair.inject(:+) 
  arr1 << pair_sum
  break if pair_sum > arr2.max
end

#Loop B - (just A condensed)
pairs.each { |pair| arr1.last <= arr2.max ? arr1 << pair.inject(:+) : break }

#Loop C
i = 0
pair_sum = 0
begin
  pair_sum = pairs[i].inject(:+)
  arr1 << pair_sum
  i += 1
end until pair_sum > arr2.max

在 Ruby 早期转义 .each { } 迭代时提出了一个类似的问题,但回答基本上是,虽然在达到目标索引时使用.eachor.each_with_index和 exiting会起作用,但更惯用。然而,在我的情况下,我事先不知道我必须迭代多少个元素,向我展示似乎是一个边界情况。break.take(num_elements).each

这是来自我已经解决的项目欧拉类型问题,顺便说一句。只是想知道社区首选的语法。提前感谢您的宝贵时间。

4

4 回答 4

8

take并且drop有一个变体take_whiledrop_while而不是提供固定数量的元素,而是提供一个块。只要块返回 true,Ruby 就会从接收器累积值(在 take_while 的情况下)。您的代码可以重写为

array.take_while {|pair| pair.sum < foo}.map(&:sum)

这确实意味着您计算其中一些对的总和两次。

于 2013-04-30T08:54:27.593 回答
4

在 Ruby 2.0 中,Enumerable#lazy它返回一个惰性枚举器:

sums = pairs.lazy.map { |a, b| a + b }.take_while { |pair_sum| pair_sum < some_max_value }.force

这避免了计算总和两次。

于 2013-04-30T09:26:25.677 回答
1
[[1, 2], [3, 4], [5, 6]].find{|x, y| x + y > 6}
# => [3, 4]
于 2013-04-30T08:56:31.920 回答
1
[[1, 2], [3, 4], [5, 6]].find{|x, y| x + y > 6}.inject(:+)
#=> 7
于 2013-04-30T09:58:05.053 回答