在Ruby中将不连续数据切换成连续的部分

时间:2013-10-15 16:00:38

标签: ruby arrays

我有这个不连续的数组:

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那样。我很有兴趣找到一个干净,优雅的解决方案。

7 个答案:

答案 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.lastnil,并且比较仍然有效。

我使用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