tags:

views:

683

answers:

10

Is there a nice quick way to get every other entry in an array in Ruby ?

Either the odd or even entries values with 0 included in the odd.

I'd like to be able to use it like this

array1 += array2.odd_values

or

puts array2.odd_values.join("-")

for example

Update

This give exactly what I'm after but I'm sure there is a shorter version.

array1.each_with_index do |item,index| 
  if (index %2 ==0) then 
    array2.push(item) 
  end
end
A: 

With a blank array A, and a full array H, something like this should work:

H.size.times do |i|
  if i % 2 == 1
    A[i/2] = H[i]
  end
end
NolanDC
+1  A: 
dst = []
array.each_slice(2) { |x| dst.push(x[1]) }

should give you an array of the odd indices.

Replace x[1] with x[0] for the even entries.

CookieOfFortune
Seems to return a nil value >> array1.each_slice(2) { |x| x[1] }=> nil>>
Dean Smith
That's an expensive eay to do it. The fastest is just to loop.
Chris McCauley
Hmmm... I guess it doesn't return a new array. Let me edit it.
CookieOfFortune
@Chris: Of course a loop would be the faster, but why not just write it in ASM while we're at it too?
CookieOfFortune
+1  A: 

This might work for you, or then again, not :-)

irb(main):050:0> all = [1,2,3,4,5,6,7,8,9]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):051:0> evens = []
=> []
irb(main):052:0> all.each_index do |i| if (i.even?): evens.push(a[i]) end end
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):053:0> evens
=> [1, 3, 5, 7, 9]
Vinko Vrsalovic
+1  A: 

Here's a code snippet that's intended to add a select_with_index method to Enumerable, which would allow you to do

array.select_with_index{|item, i| item if i % 2 == 0} for evens

array.select_with_index{|item, i| item if i % 2 == 1} for odds

JacobM
you could use `if i.even?` and `if i.odd?`
glenn jackman
A: 
module Enumerable
  def odd_values
    r = []
    self.each_index {|x| r << self[x] if x%2==0}
    r
  end
end

p ["a", "b" ,"c" ,"d" ,"e"].odd_values  #returns ["a","c","e"]
p ["a", "b" ,"c" ,"d" ,"e"].odd_values.join("-") #returns "a-c-e"

I just reused an approach i used for another question on arrays. :D

testr
+1  A: 

Another way to think about it (adds array2 evens to array1):

array1 << array2.values_at(*Array.new(array2.size/2){|i| i*2})
JRL
A: 

My take on the problem, defining simple Array extensions:

class Array
  def odd_values
    (0...length / 2).collect { |i| self[i*2 + 1] }
  end

  def even_values
    (0...(length + 1) / 2).collect { |i| self[i*2] }
  end
end

puts [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].odd_values.inspect
# => [1, 3, 5, 7, 9]

puts [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ].even_values.inspect
# => [0, 2, 4, 6, 8]

puts [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].even_values.inspect
# => [0, 2, 4, 6, 8]

puts [ ].even_values.inspect
# => []
tadman
+2  A: 
a = ('a'..'z').to_a

a.values_at(* a.each_index.select {|i| i.even?})
# => ["a", "c", "e", "g", "i", "k", "m", "o", "q", "s", "u", "w", "y"]

a.values_at(* a.each_index.select {|i| i.odd?})
# => ["b", "d", "f", "h", "j", "l", "n", "p", "r", "t", "v", "x", "z"]

So, as requested

class Array
  def odd_values
    self.values_at(* self.each_index.select {|i| i.odd?})
  end
  def even_values
    self.values_at(* self.each_index.select {|i| i.even?})
  end
end
glenn jackman
Thanks everyone, this is the closest.
Dean Smith
Dean, this includes `0` as the evens. This is inherent in using the `% 2` (or derivative) approach. I handle that in my reply.
ezpz
A: 
a = [0,1,2,3,4,5,6,7,8,9]

(1...a.size).step(2).collect { |i| a[i] }
=> [1, 3, 5, 7, 9]

(2...a.size).step(2).collect { |i| a[i] }
=> [2, 4, 6, 8]

Of course, considering 0 an odd index creates a little hackery, right? Since you will have adjacent entries that are in effect odd indicies. To compensate for that you can just add the zeroth entry to the result of the first collect. Consider:

[a[0]] + (1...a.size).step(2).collect { |i| a[i] }
=> [0, 1, 3, 5, 7, 9]

You could always compact this further and do something like:

a.values_at(*(1...a.size).step(2))
=> [1, 3, 5, 7, 9]

a.values_at(*(2...a.size).step(2))
=> [2, 4, 6, 8]

The same hack is available to handle the zeroth entry.

ezpz
A: 

Don't forget good old friend Array.inject

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] a.inject([]){|result, item| result << item if item %2 == 1; result}

Should give you odd items.

webnuwan