Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping consecutive numbers in an array

Tags:

arrays

ruby

I need to add consecutive numbers to a new array and, if it is not a consecutive number, add only that value to a new array:

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

I want to get this result:

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

Is there an easier way to do this?

like image 659
bluexuemei Avatar asked May 24 '14 02:05

bluexuemei


People also ask

How do you find consecutive numbers in an array?

Method 1 (Use Sorting) 1) Sort all the elements. 2) Do a linear scan of the sorted array. If the difference between the current element and the next element is anything other than 1, then return false. If all differences are 1, then return true.

How do you group an array?

array. groupBy(callback) accepts a callback function that's invoked with 3 arguments: the current array item, index, and the array itself. The callback should return a string: the group name where you'd like to add the item.

How do you count consecutive numbers in Java?

Approach: Initialize count = 0 and traverse the array from arr[0] to arr[n – 2]. If the current element is equal to the next element in the array then increment the count. Print the count in the end.


3 Answers

A little late to this party but:

old_array.slice_when { |prev, curr| curr != prev.next }.to_a
# => [[1, 2, 3], [5], [7, 8, 9], [20, 21], [23], [29]]
like image 116
avcJav Avatar answered Sep 28 '22 20:09

avcJav


This is the official answer given in RDoc (slightly modified):

actual = old_array.first
old_array.slice_before do
  |e|
  expected, actual = actual.next, e
  expected != actual
end.to_a
like image 28
sawa Avatar answered Sep 28 '22 21:09

sawa


A couple other ways:

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]]
like image 34
Cary Swoveland Avatar answered Sep 28 '22 21:09

Cary Swoveland