迭代Ruby数组的最惯用的方法,当满足任意条件时退出?

时间:2013-04-30 08:43:58

标签: ruby arrays loops each break

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

我已经编写了三个循环来执行此操作,所有这些循环都会产生所需的结果。我的问题是:哪个是更惯用的Ruby?或者 - 更好 - 是否有更好的方法?我尽量不使用非局部循环变量,但是break语句看起来对我的(不可否认的新手)眼睛是一种hackish。

# 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

escaping the .each { } iteration early in Ruby处提出了一个类似的问题,但回复基本上是这样的,当使用.each.each_with_index并在达到目标索引时退出break时工作,.take(num_elements).each更加惯用。然而,在我的情况下,我事先并不知道我需要迭代多少元素,向我展示看似边界的情况。

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

4 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:4)

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

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

这可以避免两次计算总和。

答案 2 :(得分:1)

[[1, 2], [3, 4], [5, 6]].find{|x, y| x + y > 6}
# => [3, 4]

答案 3 :(得分:1)

[[1, 2], [3, 4], [5, 6]].find{|x, y| x + y > 6}.inject(:+)
#=> 7