我想迭代一个数组,其中每个元素都是两个整数的数组(例如`[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
更加惯用。然而,在我的情况下,我事先并不知道我需要迭代多少元素,向我展示看似边界的情况。
这是我已经解决的项目欧拉式问题,顺便说一句。只是想知道社区首选的语法。提前感谢您宝贵的时间。
答案 0 :(得分:7)
take
和drop
有一个变体take_while
和drop_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