splitter_in_the_sun
splitter_in_the_sun

Reputation: 71

ruby/rails array all elements between two indices

I have an array like this: [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]

What's the simplest way to return each item in the array from position 6 until 0 where the resulting array looks like: [1,2,3,4,5,6,7]

This positions in the array can be dynamic, for example passing in 4 and 9 should return [11,12,1,2,3,4]

I'm wondering if there's a method that accomplishes this in Rails api.

Thanks in advance

EDIT Let's assume that no negative numbers, so doing array[2..-2] wont work.

Array#splice almost works for this, but if the second position is less than the first, it returns nil.

Upvotes: 6

Views: 1759

Answers (7)

webster
webster

Reputation: 4012

def foo a, s, e
  a = e < s ? (a[s,a.size] << a[0..e]).flatten : a[s..e]
end

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
a = foo(a, 6, 0) # => [1, 2, 3, 4, 5, 6, 7]
a = foo(a, 4, 9) # => [11, 12, 1, 2, 3, 4]

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

A couple more ways (my preference being for #1).

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]

#1

def foo a, min, max
  as = a.size
  max += as if max < min
  (min..max).map { |i| a[i%as] }
end

foo(a, 6, 0) # => [ 1,  2, 3, 4, 5, 6, 7]
foo(a, 4, 9) # => [11, 12, 1, 2, 3, 4]

#2

def foo a, min, max
  max += a.size if max < min
  e = a.cycle
  min.times { e.next }
  (max-min+1).times.map { e.next }
end

foo(a, 6, 0) # => [ 1,  2, 3, 4, 5, 6, 7]
foo(a, 4, 9) # => [11, 12, 1, 2, 3, 4]

Upvotes: 0

BinaryMee
BinaryMee

Reputation: 2142

class Array
   def get_sub_array(start,last)
       (start > last) ? (self[start..-1] + self[0..last]) : self[start..last]
   end
end

Then

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
a.get_sub_array(6,0)
#[1, 2, 3, 4, 5, 6, 7]

Or if you don't want to monkey patch

You could have a method like

def get_sub_array(array, start,last)
   (start > last) ? (array[start..-1] + array[0..last]) : array[start..last]
end

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
get_sub_array(a,6,0)
#[1, 2, 3, 4, 5, 6, 7]

Upvotes: 2

Mandeep
Mandeep

Reputation: 9173

def some_function(some_array,start_val=6, end_val=0)
  if end_val > start_val
    some_array[start_val,(end_val - start_val)]
  else
    (some_array[start_val, some_array.size] << some_array[0, (end_val)]).flatten
  end
end

You can use ternary operator to make it one liner too:

def some_function(some_array,start_val=6, end_val=0)
  end_val > start_val ? some_array[start_val,(end_val - start_val)] : (some_array[start_val, some_array.size] << some_array[0, (end_val)]).flatten
end

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
some_function(a) # => [1, 2, 3, 4, 5, 6, 7]
some_function(a, 4, 9) # => [11, 12, 1, 2, 3, 4]

Upvotes: 1

sawa
sawa

Reputation: 168081

def foo a, min, max
  a.rotate(min).first((max - min) % a.length + 1)
end

a = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
foo(a, 6, 0) # => [1, 2, 3, 4, 5, 6, 7]
foo(a, 4, 9) # => [11, 12, 1, 2, 3, 4]

Upvotes: 4

Triveni Badgujar
Triveni Badgujar

Reputation: 941

min=6
max=0
arr = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
result = []
if max<min
  result << arr[min..arr.length]
  result << arr[0..max]
else
  result << arr[min..max]
end

Upvotes: 0

cubsker
cubsker

Reputation: 470

myArray = [7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
myArray[6..-1] returns [1, 2, 3, 4, 5, 6]
myArray[4..9] returns [11,12,1,2,3,4]

Upvotes: -1

Related Questions