从Ruby中的数组中选择连续的整数

Mer*_*ami -4 ruby arrays

我想从数组中选择连续的整数,例如:

输入:(不必排序)

array = [1, 3, 6, 7, 8, 9, 10, 12, 13, 17]
Run Code Online (Sandbox Code Playgroud)

预期产量:

#=> [6, 7, 8, 9, 10, 12, 13]
Run Code Online (Sandbox Code Playgroud)

到目前为止这是我的代码:

array = [1, 3, 9, 6, 7, 10, 8, 12, 13, 17]
newarray = []
z = 0
array.sort.each_cons(2) do |x, y|
  if y == x + 1
    if z == 0
      newarray.insert(0, x, y)
    else
      newarray.push(y)
    end
  end
  z = z + 1
end

newarray #=> [7, 8, 9, 10, 13]
Run Code Online (Sandbox Code Playgroud)

如你所见,6并且12缺失了.

我的代码有什么问题 - 除了bug之外 - 是否有更好的方法来编写它?

Ste*_*fan 5

您的代码进行比较相邻的元件xy,但推xy仅当它们在阵列中的第一个元素(if z == 0; newarray.insert(0, x, y)).否则,仅y推送,因此缺少每组连续整数的第一个元素.

此表说明了正在发生的事情:

  x   y   y == x+1
--------------------
  1   3   false
  3   6   false
  6   7   true      #=> push(7)
  7   8   true      #=> push(8)
  8   9   true      #=> push(9)
  9  10   true      #=> push(10)
 10  12   false
 12  13   true      #=> push(13)
 13  17   false
Run Code Online (Sandbox Code Playgroud)

您可以使用z作为组开头的指示符来修复代码:

z = true
array.sort.each_cons(2) do |x, y|
  if y == x + 1
    if z
      newarray.push(x, y)
      z = false
    else
      newarray.push(y)
    end
  else
    z = true
  end
end
Run Code Online (Sandbox Code Playgroud)

更好的方法是使用chunk_whileRuby 2.3中引入的:

array = [1, 3, 9, 6, 7, 10, 8, 12, 13, 17]

array
  .sort                              #=> [1, 3, 6, 7, 8, 9, 10, 12, 13, 17]
  .chunk_while { |x, y| y == x + 1 } #=> [[1], [3], [6, 7, 8, 9, 10], [12, 13], [17]]
  .select { |a| a.size > 1 }         #=> [[6, 7, 8, 9, 10], [12, 13]]
  .flatten                           #=> [6, 7, 8, 9, 10, 12, 13]
Run Code Online (Sandbox Code Playgroud)

您是否注意到该文档包含类似的示例?

例如,逐个增加的子序列可以按如下方式分块:

a = [1,2,4,9,10,11,12,15,16,19,20,21]
b = a.chunk_while {|i, j| i+1 == j }
p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
Run Code Online (Sandbox Code Playgroud)