比较数组中元素的总和:Ruby

时间:2014-08-15 11:11:12

标签: ruby arrays sorting

我需要检查数组中任何2个元素的总和是否等于给定的数字。这就是我提出的,但它似乎没有进行比较

def sum_comparison(int_array, x)
  n = int_array.length
  (0..n).each do |i|
    (1..n).each do |j|
      if ((int_array[i].to_i + int_array[j].to_i) == x)
        return true
      else
        return false
      end
    end
  end
end

4 个答案:

答案 0 :(得分:7)

你的解决方案似乎过于复杂,并且受到像C这样的低级过程语言的编程风格的强烈影响。一个明显的问题是你写的

n = int_array.length
(0..n).each do |i|
  # use int_array[i].to_i inside the loop
end

现在在each循环中,您将获得数字i = 0, 1, 2, ..., n,例如int_array = [3,4,5]获得i = 0, 1, 2, 3。请注意,有四个元素,因为您从零开始计数(这被称为关闭一个错误)。这最终会导致n的数组访问,这是一个超出数组末尾的访问。这将再次导致nil返回,这可能是您使用to_i将其转换回整数的原因,因为否则您将获得TypeError: nil can't be coerced into Fixnum进行添加。您可能想要的只是:

int_array.each do |i|
  # use i inside the loop
end

对于示例数组[3,4,5],这实际上会导致i = 3, 4, 5。要以更Ruby方式获取数组的组合,您可以使用Array#combination。同样,您可以使用Array#any?检测是否有任何组合满足指定条件:

def sum_comparison(array, x)
  array.combination(2).any? do |a, b|
    a + b == x
  end
end

答案 1 :(得分:5)

当你的函数比较第一个元素时,它会立即返回false。你需要在迭代时返回true,如果没有找到,则返回false,以避免这个问题:

def sum_comparison(int_array, x)
  n = int_array.size
  (0...n).each do |i|
    (1...n).each do |j|
      if (int_array[i].to_i + int_array[j].to_i) == x
        return true
      end
    end
  end
  false
end

为简化此操作,您可以使用permutationcombinationany?方法,如@ p11y所示。要获得已创建的元素,您可以使用find or detect

def sum_comparison(a, x)
  a.combination(2).any? { |i, j| i + j == x }
end

a.combination(2).detect { |i, j| i + j == x }
# sum_comparison([1,2,3, 4], 6) => [2, 4]

答案 2 :(得分:3)

使用枚举器:

#!/usr/bin/env ruby

def sum_comparison(int_array, x)
  enum = int_array.to_enum
  loop do
    n = enum.next
    enum.peek_values.each do |m|
      return true if (n + m) == x
    end
  end
  false
end

puts sum_comparison([1, 2, 3, 4], 5)

输出:

true

答案 3 :(得分:1)

<强>问题

您的方法相当于:

def sum_comparison(int_array, x)
  return int_array[0].to_i + int_array[1].to_i == x
end

因此,

int_array = [1,2,4,16,32,7,5,7,8,22,28]
sum_comparison(int_array, 3) #=> true, just lucky!
sum_comparison(int_array, 6) #=> false, wrong!

<强>替代

这是一个相对有效的实施,当然比使用Enumerable#combination更有效。

<强>代码

def sum_comparison(int_array, x)
  sorted = int_array.sort
  smallest = sorted.first
  sorted_stub = sorted.take_while { |e| e+smallest <= x }
  p "sorted_stub = #{sorted_stub}"
  return false if sorted_stub.size < 2
  loop do
    return false if sorted_stub.size < 2
    v = sorted_stub.shift
    found = sorted_stub.find { |e| v+e >= x }
    return true if found && v+found == x
  end
  false
end

<强>实施例

sum_comparison([7,16,4,12,-2,5,8], 3)
  # "sorted_stub = [-2, 4, 5]"
  #=> true
sum_comparison([7,16,4,12,-2,5,8], 7)
  # "sorted_stub = [-2, 4, 5, 7, 8]"
  #=> false
sum_comparison([7,16,4,22,18,12,2,41,5,8,17,31], 9)
  # "sorted_stub = [2, 4, 5, 7]"
  #=> true

备注

  • 仅包含行p "sorted_stub = #{sorted_stub}"以显示示例中的数组sorted_stub

  • e+smallest > xfg sortedg >= ef < g的任何元素f+g >= e+smallest > x sorted_stub.last }。因此,sortedv中需要考虑的最大值。

  • 对于给定值found = sorted_stub.find { |e| v+e >= x },第e行会在找到v+e = x e后立即停止搜索v+e >= x {{1}}这样{{1}}。然后,下一行确定是否找到了匹配项。