如何在 Ruby 中将整数数组压缩为范围和整数数组

ico*_*ast 1 ruby arrays range

我有一个排序的整数数组,并希望用一个范围替换连续整数的所有子集,以便:

[1,2,3,4,5,6,7,8,9,10,42]
Run Code Online (Sandbox Code Playgroud)

替换为:

[1..10,42]
Run Code Online (Sandbox Code Playgroud)

这是用户未正确输入且无法导入其他系统数据库的 Google 电子表格中的行列表。有很多行,通常有几十行。用户更容易看到第 3201-3379 行都是坏的,而不必单独读取每个行号。

我不是要求“将整数数组转换为范围数组”。

我知道如何编写代码,我很乐意这样做,但如果有人已经这样做了,我就不乐意了。我当前的代码并不优雅,如果已经有一些经过良好测试和优化的东西,我不会费心重构它。

Car*_*and 6

我希望在 SO 上已经问过这个问题,但答案不在我的 Rolodesk 中。然而,这很容易做到。

arr = [1, 2, 3, 5, 6, 7, 8, 10, 12, 13, 14, 17, 18, 20]

arr.slice_when { |x,y| y > x+1 }.
    map { |a| a.size == 1 ? a.first : a.first..a.last }
  #=> [1..3, 5..8, 10, 12..14, 17..18, 20]
Run Code Online (Sandbox Code Playgroud)

参见Enumerable#slice_when

我们首先计算枚举数

enum = arr.slice_when { |x,y| y > x+1 }
  #=> #<Enumerator: #<Enumerator::Generator:0x...0000...fe0>:each>
Run Code Online (Sandbox Code Playgroud)

我们可以转换enum为数组以查看将由枚举器生成并馈送到 的元素map

enum.to_a
  #=> [[1, 2, 3], [5, 6, 7, 8], [10], [12, 13, 14], [17, 18], [20]]
Run Code Online (Sandbox Code Playgroud)

作为练习,看看是否有另一种Enumerable方法可以代替slice_when. (提示:考虑花生酱大辩论。)