2014-05-24 79 views
2

我需要連續號碼添加到新陣列,如果它是不連續的號碼,只值添加到一個新的數組:連續的分組編號在數組

old_array = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29] 

我想這結果:

new_array = [ 
    [1,2,3], 
    [5], 
    [7,8,9] 
    [20,21] 
    [23], 
    [29] 
] 

是否有更簡單的方法來做到這一點

+3

這是學校?你有什麼嘗試?你在尋求幫助還是爲了我們爲你做? – DutGRIFF

+0

'new_array'的條件? –

+0

相關問題:http://stackoverflow.com/q/3728660/38765 –

回答

8

這是RDoc給出(略有修改),官方的回答:

actual = old_array.first 
old_array.slice_before do 
    |e| 
    expected, actual = actual.next, e 
    expected != actual 
end.to_a 
+0

如何在ruby 1.8.7中編寫代碼? – bluexuemei

+2

Ruby 1.8.7不再被維護,並且包含幾個已知的安全漏洞。你應該避免使用它。 –

+0

很好的答案,謝謝 – bluexuemei

2

一對夫婦的其他方式:

old_array = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29] 

#1

a, b = [], [] 
enum = old_array.each 
loop do 
    b << enum.next 
    unless enum.peek.eql?(b.last.succ) 
    a << b 
    b = [] 
    end 
end 
a << b if b.any? 
a #=> [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 

#2

def pull_range(arr) 
    b = arr.take_while.with_index { |e,i| e-i == arr.first } 
    [b, arr[b.size..-1]] 
end 

b, l = [], a 
while l.any? 
    f, l = pull_range(l) 
    b << f 
end 
b #=> [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 
+0

可能不應該這樣說,但那先生是一件藝術品! –

+0

感謝恭維,@約翰。 (約翰指的是#1;後來我加了#2)。 –

0

你也可以做這樣的:

old_array=[1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29] 
new_array=[] 
tmp=[] 
prev=nil 
for i in old_array.each 
    if i != old_array[0] 
     if i - prev == 1 
      tmp << i 
     else 
      new_array << tmp 
      tmp=[i] 
     end 
     if i == old_array[-1] 
      new_array << tmp 
      break 
     end 
     prev=i 
    else 
     prev=i 
     tmp << i 
    end 
end 
0

使用chunk你可以這樣做:

old_array.chunk([old_array[0],old_array[0]]) do |item, block_data| 
    if item > block_data[1]+1 
    block_data[0] = item 
    end 

    block_data[1] = item 
    block_data[0] 
end.map { |_, i| i } 
# => [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 
1

一些答案似乎不必要的長時間,就可以做到這一點非常緊湊的方式:

arr = [1, 2, 3, 5, 7, 8, 9, 20, 21, 23, 29] 
arr.inject([]) { |a,e| (a[-1] && e == a[-1][-1] + 1) ? a[-1] << e : a << [e]; a } 
# [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 

另外,先從第一個元素,以擺脫a[-1]條件(需要的情況下,當a[-1]nil,因爲a是空的):

arr[1..-1].inject([[arr[0]]]) { |a,e| e == a[-1][-1] + 1 ? a[-1] << e : a << [e]; a } 
# [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 

Enumerable#inject迭代可枚舉的所有元素,建立其與給定的對象開始的結果值。我在我的解決方案中分別給它一個空數組或第一個數組,其中第一個數值包含在數組中。然後我簡單地檢查我們迭代的輸入數組的下一個元素是否等於結果數組中最後一個數組的最後一個值加上1(即,如果它是下一個連續元素)。如果是,我將它追加到最後一個列表中。否則,我用它中的那個元素開始一個新的列表,並將它追加到結果數組中。

+0

很好的答案,謝謝 – bluexuemei

0

使用哈希你可以這樣做:

counter = 0 
groups = {} 
old_array.each_with_index do |e, i| 
    groups[counter] ||= [] 
    groups[counter].push old_array[i] 
    counter += 1 unless old_array.include? e.next 
end 
new_array = groups.keys.map { |i| groups[i] } 
3

有點晚了這個晚會,但是:

old_array.slice_when { |prev, curr| curr != prev.next }.to_a 
# => [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]] 
+1

+1。 'slice_when'被[添加](https://bugs.ruby-lang.org/issues/9826)到ruby版本'2.2',並且提供了比這些舊的答案更優雅的解決方案。 –