如何在数组中找到总计为10的元素

时间:2017-02-07 20:39:35

标签: ruby

我正在尝试在数组中打印最多加10的元素,但是我收到了这个错误:

 8 : 25 : 55 : 5TypeError: nil can't be coerced into Fixnum 

这是我的代码:

array =  [6, 2, 7, 1, 10, 9, 0, 8, 2, 10, 10, 3, 5, 7, 2, 5, 5, 5]
def print(array)
  array.each_with_index.inject(0) do |m,(roll,i)|
    if array[i] + array[i+1] == 10 
      print "#{array[i]} : #{array[i+1]}"
    end
  end
end

我想要的输出是:

8:2,5:5

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

array =  [6, 2, 7, 1, 10, 9, 0, 8, 2, 10, 10, 3, 5, 7, 2, 5, 5, 5]

array.flat_map { |n| n == 10 ? [10, 0] : n }.
      each_slice(2).
      select { |ball1,ball2| ball1 != 10 && ball1+ball2.to_i == 10 }
  #=> [[8, 2], [5, 5]] 

步骤如下。首先,使用Enumerable#flat_map在每个10之后插入零(在保龄球中,罢工):

a = array.flat_map { |n| n == 10 ? [10, 0] : n }
  #=> [6, 2, 7, 1, 10, 0, 9, 0, 8, 2, 10, 0, 10, 0, 3, 5, 7, 2, 5, 5, 5] 

这允许我们使用Enumerable#each_slicearray划分为成对:

e = a.each_slice(2)
  #=> #<Enumerator: [6, 2, 7, 1, 10, 0, 9, 0, 8, 2, 10, 0, 10, 0, 3, 5, 7, 2, 5, 5, 5]
  #   :each_slice(2)> 

我们可以使用Enumerable#entries(或Enumerable#to_a)查看此枚举器将生成​​的值并传递给select

e.entries
  #=> [[6, 2], [7, 1], [10, 0], [9, 0], [8, 2], [10, 0], [10, 0], [3, 5],
  #    [7, 2], [5, 5], [5]] 

注意最后一个[5]的数组。接着,

e.select { |ball1,ball2| ball1 != 10 && ball1+ball2.to_i == 10 }
  #=> [[8, 2], [5, 5]] 

当生成e[5])的最后一个元素时,select的块变量计算如下:

ball1, ball2 = [5]
  #=> [5] 
ball1
  #=> 5 
ball2
  #=> nil 

如果上面的块包含&& ball1+ball2 == 10,则会引发异常(除非在示例的公式中包含array的最后一个元素是错误的)。这可以用if ball2.nil? ...语句处理,但我选择简单地将ball2转换为整数。如果它已经是整数,则返回该值;它等于nilnil.to_i #=> 0。请参阅NilClass#to_i

答案 1 :(得分:1)

#inject是一种奇怪的方法,可用于此目的。你写它的方式,nil作为聚合器返回,这就是你没有得到所需结果的原因。删除它,逻辑更清晰:

array =  [6, 2, 7, 1, 10, 9, 0, 8, 2, 10, 10, 3, 5, 7, 2, 5, 5, 5]
def print(array)
  pairs = []
  array.each_with_index do |val, idx|
    next if idx == 0
    prev_val = array[idx - 1]
    curr_total = val + prev_val
    if curr_total == 10
      pairs << [prev_val, val]
    end
  end

  pairs.map { |pair| pair.join(':') }.join(',')
end