4

我有这个不连续的数组:

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。我对找到一个干净、优雅的解决方案很感兴趣。

4

7 回答 7

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]]
于 2013-10-15T16:25:41.137 回答
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]]
于 2013-10-15T16:43:03.687 回答
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]]
于 2013-10-15T16:11:55.513 回答
1
arr.slice_before([]) {|elt, state|
  (elt-1 != state.last).tap{ state << elt }
}.to_a

解释:

state基本上是 , 的不断增长的副本arr,并被初始化为传递给 的参数的副本slice_beforestate.last表示前一个元素。请注意,在第一次迭代中,state.lastnil,并且比较仍然有效。

tap用来构建state但也让比较结果返回。我可以使用begin/ ensure,或分配给变量,但tap更短。顺序在这里很重要 - 我只能在进行比较后追加。

另一个优点是我不必从块内部引用任何外部变量,也不必使用arr.

于 2013-10-15T20:20:19.000 回答
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
于 2013-10-15T17:19:46.467 回答
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]
于 2013-10-15T16:18:13.010 回答
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
于 2013-10-15T17:25:30.830 回答