Odd (or even) entries in a Ruby Array

Ruby

Ruby Problem Overview


Is there a 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

Ruby Solutions


Solution 1 - Ruby

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

Solution 2 - Ruby

...

arr = ["0", "1", "2", "3"]
arr.select.each_with_index { |_, i| i.odd? }
arr.select.each_with_index { |_, i| i.even? }

As floum pointed out, in Ruby 2.2 you can simply do:

arr.select.with_index { |_, i| i.odd? }

Solution 3 - Ruby

left,right = a.partition.each_with_index{ |el, i| i.even? }

Solution 4 - Ruby

You can just use this:

(1..6).partition { |v| v.even? }  #=> [[2, 4, 6], [1, 3, 5]]

From Ruby docs: Ruby Docs Reference

Solution 5 - Ruby

Some crazy way using facets:

require 'facets'
array = [1,2,3,4,5]
odd = array.to_h.keys # 1,3,5
even = array.to_h.values.compact # 2,4

Solution 6 - Ruby

This will probably never be read, but...

Simple and clean:

array2.map{ |n| n if n % 2 == 0 }.compact # evens

array2.map{ |n| n if n % 2 == 1 }.compact # odds

Just found an even more terse way (gotta love Ruby):

array2.find_all{ |n| n % 2 == 0 } # evens

array2.reject  { |n| n % 2 == 0 } # odds

Solution 7 - Ruby

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.

Solution 8 - Ruby

odds = array.each_slice(2).map(&:first)
evens = array.each_slice(2).map(&:last)

Solution 9 - Ruby

For the record:

a = [1,2,3,4,5,6]
h = Hash[*a]
evens = h.keys
odds = h.values

I'm using the 'splat' operator of Array to get comma separated values and pass that to Hash which accepts arguments as alternating keys/values.

Solution 10 - Ruby

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

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

Solution 11 - Ruby

This seems like the most Rubyish solution, combining the best of JacobM and glenn jackman's approaches.

module ::Enumerable
  def select_with_index
    index = -1
    select { |x| yield(x, (index += 1)) }
  end
  def odds
    select_with_index {|x,i| i.odd?}
  end
  def evens
    select_with_index {|x,i| i.even?}
  end
end

Solution 12 - Ruby

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

Solution 13 - Ruby

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]

Solution 14 - Ruby

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

Solution 15 - Ruby

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
# => []

Solution 16 - Ruby

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.

Solution 17 - Ruby

evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Solution 18 - Ruby

a = [1,2,3,4,5]
a.in_groups_of(2).map(&:first) => odds
a.in_groups_of(2).map(&:last) => evens

Solution 19 - Ruby

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

Solution 20 - Ruby

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.

Solution 21 - Ruby

I suggest the use of Enumerable#Inject function

array = (1..30)    
array.inject({even: [], odd: []}){|memo, element| memo[element.even? ? :even : :odd] << element; memo}

Solution 22 - Ruby

Slightly left field, but I recently needed something I could pass to select as a proc:

def alternator
  gen = [true,false].cycle
  proc { gen.next }
end

self.filter = alternator

# ... elsewhere/much later ...
input = 'a'..'z'
input.select(&filter)

Some may suggest this could even be a case for Enumerator.new or even a Fiber, which would both technically be simpler constructs, but I think at the expense of clarity.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDean SmithView Question on Stackoverflow
Solution 1 - Rubyglenn jackmanView Answer on Stackoverflow
Solution 2 - RubyDamien RocheView Answer on Stackoverflow
Solution 3 - RubyJames EJView Answer on Stackoverflow
Solution 4 - RubyNikeshView Answer on Stackoverflow
Solution 5 - RubyAlexander ParamonovView Answer on Stackoverflow
Solution 6 - RubyleetheguyView Answer on Stackoverflow
Solution 7 - RubyCookieOfFortuneView Answer on Stackoverflow
Solution 8 - Rubybwv549View Answer on Stackoverflow
Solution 9 - RubyJeroen RosenbergView Answer on Stackoverflow
Solution 10 - RubyJRLView Answer on Stackoverflow
Solution 11 - RubyAlexChaffeeView Answer on Stackoverflow
Solution 12 - RubyNolanDCView Answer on Stackoverflow
Solution 13 - RubyVinko VrsalovicView Answer on Stackoverflow
Solution 14 - RubyJacob MattisonView Answer on Stackoverflow
Solution 15 - RubytadmanView Answer on Stackoverflow
Solution 16 - RubyezpzView Answer on Stackoverflow
Solution 17 - RubytomekfranekView Answer on Stackoverflow
Solution 18 - Rubyc.apolzonView Answer on Stackoverflow
Solution 19 - RubytestrView Answer on Stackoverflow
Solution 20 - RubywebnuwanView Answer on Stackoverflow
Solution 21 - Rubyuser785665View Answer on Stackoverflow
Solution 22 - RubyinopinatusView Answer on Stackoverflow