我有这个不连续的数组:
a = [1, 2, 3, 7, 8, 10, 11, 12]
我需要它是一个连续数组的数组:
[[1, 2, 3], [7, 8], [10, 11, 12]]
我循环遍历原始数据,将每个值与最后一个值进行比较以构建新数组:
parts = []
last = nil
a.each do |n|
parts.push [] if last.nil? || last+1 != n
parts.last.push n
last = n
end
感觉很脏而且不像Ruby那样。我很有兴趣找到一个干净,优雅的解决方案。
答案 0 :(得分:2)
@ hirolau的修改版本。
a = [1, 2, 3, 7, 8, 10, 11, 12]
prev = a[0] - 1
a.slice_before { |cur| [prev + 1 != cur, prev = cur][0] }.to_a
# => [[1, 2, 3], [7, 8], [10, 11, 12]]
prev = a[0] - 1
a.slice_before { |cur|
discontinuous = prev + 1 != cur
prev = cur
discontinuous
}.to_a
# => [[1, 2, 3], [7, 8], [10, 11, 12]]
答案 1 :(得分:2)
([a[0]] + a).each_cons(2).slice_before{|k, l| k + 1 != l}.map{|a| a.map(&:last)}
# => [[1, 2, 3], [7, 8], [10, 11, 12]]
答案 2 :(得分:1)
可枚举文档中的修改示例:
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-slice_before
a = [1, 2, 3, 7, 8, 10, 11, 12]
prev = a.first
p a.slice_before { |e|
prev, prev2 = e, prev
prev2 + 1 != e
}.to_a # => [[1, 2, 3], [7, 8], [10, 11, 12]]
答案 3 :(得分:1)
似乎有很多方法可以做到这一点。
a.each_cons(2).each_with_object([[ a.first ]]) do |pair, con_groups|
con_groups.push( [] ) if pair.reduce( :-) < -1
con_groups.last.push( pair.last )
end
答案 4 :(得分:1)
arr.slice_before([]) {|elt, state|
(elt-1 != state.last).tap{ state << elt }
}.to_a
说明:
state
基本上是arr
的增长副本,并初始化为传递给slice_before
的参数的副本。 state.last
代表前一个元素。请注意,在第一次迭代中,state.last
为nil
,并且比较仍然有效。
我使用tap
构建state
,但也让比较结果返回。我可以使用begin
/ ensure
或分配给变量,但tap
更短。订单在这里很重要 - 我只能在进行比较后追加。
另一个优点是我不必从块内部引用任何外部变量,也不必使用arr
的修改版本。
答案 5 :(得分:0)
替代方案,不如提议的那样好,但更接近你自己的,更具可读性
a = [1, 2, 3, 7, 8, 10, 11, 12]
a.each_with_object({ last: nil, result: [] }) do | n, memo|
memo[:result] << [] unless memo[:last] && memo[:last] + 1 == n
memo[:result].last << n
memo[:last] = n
end[:result]
答案 6 :(得分:0)
有趣的问题,tybro0103 ......这就是我想出来的
tarr = [1, 2, 3, 7, 8, 10, 11, 12]
out = []
tarr.count.times do
i = 0 unless tarr[0].nil? && break
while tarr[0..i] == (0..i).map {|x| tarr[0] + x }
i+=1
end
out << tarr.shift(i)
end