如何使用Ruby创建一个嵌套循环“正确的方法!”?

时间:2013-10-15 00:29:13

标签: ruby-on-rails ruby arrays loops

我正在学习Ruby,接受伯克利的MOOC,而且在其中一些MOOC的作业中我们有一个练习:

  

定义方法sum_to_n?它采用一个整数数组和一个   附加整数n,作为参数,如果有的话,返回true   整数数组中的元素总和为n。一个空数组应该总和   根据定义为零。

我已经创建了两个可以完成这项工作的方法,但是我对它们中的任何一个都不满意,因为我认为它们不是用Ruby方式编写的。我希望你们中的一些人可以帮助我学习哪种方法是正确的!

我制作的第一个方法对两次迭代使用each方法,但我不喜欢这种方法的是每个数字都与其他所有数字相加,即使数字相同,也可以这样做这样:

arr[1, 2, 3, 4] => 1+1, 1+2, 1+3, 1+4, 2+1, 2+2, 2+3, 2+4, 3+1, 3+2... 4+3, 4+4

正如你所看到的,有很多重复的总和,我不希望这样。

这是代码:

def sum_to_n?(arr, n)
  arr.each {|x| arr.each {|y| return true if x + y == n && x != y}}
  return true if n == 0 && arr.length == 0
  return false
end

通过我得到了我想要的,只是一个简单计算而无需重复任何人,甚至同样的数量相加的另一种方法,但它看起来太可怕了,我敢肯定有人会爱杀我做这个方式,但是你可以看到这个方法做得很好:

arr[1, 2, 3, 4] => 1+2, 1+3, 1+4, 2+3, 2+4, 3+4

这是代码:

def sum_to_n?(arr, n)
  for i in 0..arr.length - 1
    k = i + 1
    for k in k..arr.length - 1
      sum = arr[i] + arr[k]
      if sum == n
        return true
      end
    end
  end
  return true if n == 0 && arr.length == 0
  return false
end

好吧,我希望你们在尝试做一个更好,更漂亮的方法时玩得很开心。

感谢您的帮助。

4 个答案:

答案 0 :(得分:19)

我会这样写:

def sum_to_n?(arr, n)
  return true if arr.empty? && n.zero?
  arr.combination(2).any? {|a, b| a + b == n }
end

这似乎是一个非常漂亮的Rubyish解决方案。

答案 1 :(得分:2)

除了@ jorg-w-mittag的回答。我找到了另一种使用“置换”的解决方案。

https://stackoverflow.com/a/19351660/66493

def sum_to_n?(arr, n)
  (arr.empty? && n.zero?) || arr.permutation(2).any? { |a, b| a + b == n }
end

我以前不知道排列。 仍然喜欢@ jorg-w-mittag,因为它更具可读性。

答案 2 :(得分:1)

这个会在O(n.log(n))而不是O(n²)

中执行
a = 1, 2, 3, 4

class Array
  def sum_to? n
    unless empty?
      false.tap {
        i, j, sorted = 0, size - 1, sort
        loop do
          break if i == j
          a, b = sorted[i], sorted[j]
          sum = a + b
          return a, b if sum == n
          sum < n ? i += 1 : j -= 1
        end
      }
    end
  end
end

a.sum_to? 7 #=> [3, 4]

答案 3 :(得分:0)

我曾经想过,对这个问题的任何答案的开头都应该从修剪数据的多余数据开始:

无法使用此功能:

  arr.select! { |e| e <= n } # may be negative values      

但这可能有所帮助:

  arr.sort!
  while arr[0] + arr[-1] > n # while smallest and largest value > n
    arr.delete_at(-1) # delete largest vaue
  end