我想接受输入,例如:
[1,2,4,5,6,7,9,13]
并将其转换为以下内容:
[[1,2],[4,7],[9,9],[13,13]]
每个子数组代表一个整数范围。
答案 0 :(得分:21)
使用Enumerable#chunk的功能方法:
ranges = [1, 2, 4, 5, 6, 7, 9, 13]
.enum_for(:chunk) # .chunk for Ruby >= 2.4
.with_index { |x, idx| x - idx }
.map { |_diff, group| [group.first, group.last] }
#=> [[1, 2], [4, 7], [9, 9], [13, 13]]
工作原理:一旦索引,数组中的连续元素具有相同的x - idx
,因此我们使用该值来对输入数组进行块(连续项的分组)。最后,我们只需要采用每个组的第一个和最后一个元素来构建对。
答案 1 :(得分:5)
这几乎直接来自enumerable#slice_before方法文档:
ar = [1,2,4,5,6,7,9,13]
prev = ar[0]
ar.slice_before{|e|prev,prev2 = e,prev; prev2.succ != e}.map{|a|a.first..a.last}
#=> [1..2, 4..7, 9..9, 13..13]
这应该适用于使用.succ
方法的字符,日期和任何内容。
答案 2 :(得分:4)
比@tokland's very nice one使用chunk_while
更简单的解决方案:
xs.chunk_while { |a, b| a + 1 == b }.map do |seq|
[seq.first, seq.last]
end
注意:在Ruby 2.3中引入了chunk_while
答案 3 :(得分:3)
[1,2,4,5,6,7,9,13].inject([]) do |m, v|
if m.last.to_a.last == v.pred
m[-1][-1] = v
else
m << [v, v]
end
m
end
答案 4 :(得分:0)
另一种方法
def summarize(x)
x.inject([]) do |acc, value|
if acc.last && acc.last[1] + 1 == value
acc.last[1] = value
acc
else
acc << [value,value]
end
end
end
与Larsenal的方法类似,但使用注入来管理无聊的东西。