Odd (Or Even) Entries in a Ruby Array

Odd (or even) entries in a Ruby Array

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

Selecting the odd or even elements out of an array

If you add this code you have 2 handy methods to select odd or even values from an array

class Array
def odd_values
values_at(* each_index.select(&:odd?))
end
def even_values
values_at(* each_index.select(&:even?))
end
end

Ruby .each_slice with condition even and odd indexes of an array

newArrayOne, newArrayTwo = array.partition.with_index { |_,i| i.even? }

Sort odd numbers in array while keeping even numbers in place

Here are a couple of ways to do that.

arr = [7, 5, 35, 8, 12, 17, 47, 47, 37, 64, 22, 55, 13]

Both begin with the following calculation

odd, even = arr.each_with_index.partition { |n,i| n.odd? }
#=> [[[7, 0], [5, 1], [35, 2], [17, 5], [47, 6], [47, 7], [37, 8], [55, 11], [13, 12]],
# [[8, 3], [12, 4], [64, 9], [22, 10]]]
odd
#=> [[7, 0], [5, 1], [35, 2], [17, 5], [47, 6], [47, 7], [37, 8], [55, 11], [13, 12]]
even
#=> [[8, 3], [12, 4], [64, 9], [22, 10]]

See Enumerable#each_with_index, Enumerable#partition and Integer#odd?.

#1

   odd_val, odd_idx = odd.transpose
#=> [[7, 5, 35, 17, 47, 47, 37, 55, 13],
# [0, 1, 2, 5, 6, 7, 8, 11, 12]]
a = even.concat(odd_val.sort.zip(odd_idx))
#=> [[8, 3], [12, 4], [64, 9], [22, 10], [5, 0], [7, 1], [13, 2],
# [17, 5], [35, 6], [37, 7], [47, 8], [47, 11], [55, 12]]
h = a.map(&:reverse).to_h
#=> {3=>8, 4=>12, 9=>64, 10=>22, 0=>5, 1=>7, 2=>13, 5=>17, 6=>35, 7=>37,
# 8=>47, 11=>47, 12=>55}
h.values_at(*0..arr.size-1)
#=> [5, 7, 13, 8, 12, 17, 35, 37, 47, 64, 22, 47, 55]

Note:

odd_val.sort.zip(odd_idx)
#=> [5, 7, 13, 17, 35, 37, 47, 47, 55].zip([0, 1, 2, 5, 6, 7, 8, 11, 12])
#=> [[5, 0], [7, 1], [13, 2], [17, 5], [35, 6], [37, 7], [47, 8], [47, 11], [55, 12]]

See Array#sort, Array#zip and Hash#values_at.

#2

a = odd.map(&:first).sort
#=> [5, 7, 13, 17, 35, 37, 47, 47, 55]
even.each { |n,i| a.insert(i,n) }
a #=> [5, 7, 13, 8, 12, 17, 35, 37, 47, 64, 22, 47, 55]

See Array#insert.

Need help filtering an array?

You want to delete odd numbers but your program is deleting even numbers (x % 2 == 0 checks if x is an even number)

METHOD 1:

arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
arr.delete_if &:odd?

print arr

delete_if iterates by incrementing the index for arr, and deletes an element immediately after evaluating the block &:odd? with respect to the element. In other words, it is going through each element in array, and deleting the element if &:odd? is true.

&:odd?: a lambda function passing in an object to the odd? method, which returns true if the object is an odd number. Further explanations can be found what is the functionality of "&: " operator in ruby?

Note that method 1 actually MODIFIES the original array. For a way to create a new array of non-odd numbers, there is...

METHOD 2:


non_odds = arr.select{|i| not i.odd?}

Ruby sorting even and odd numbers issue

First off, let's fix your indentation (and convert to standard Ruby community coding style), so that we can better see what's going on:

[1, 2, 3, 4, 5, 6].sort do |x, y|
if x.odd? && y.odd?
0
elsif x.odd?
-1
else
1
end

if (x.odd? && y.odd?) || (x.even? && y.even?)
x <=> y
end
end

Now, the problem becomes obvious: your first conditional expression evaluates to 0, -1, or 1, but nothing is being done with this value. The value is not stored in a variable, not passed as an argument, not returned. It is simply ignored. The entire expression is a NO-OP.

Which means that the only thing that matters is this:

  if (x.odd? && y.odd?) || (x.even? && y.even?)
x <=> y
end

This will return 0 for two elements that are equal, -1 or 1 for two elements that are unequal but both odd or both even, and nil (which to sort means "these two elements are un-comparable, they don't have a defined relative ordering") for elements where one element is odd and one is even. Since sort requires all elements to be comparable, it will then abort.

The easiest way to approach this problem would probably be to partition the array into odds and evens, sort them separately, and then concatenate them:

[1, 2, 3, 4, 5, 6].partition(&:odd?).map(&:sort).inject(:concat)
#=> [1, 3, 5, 2, 4, 6]

Or do it the other way round, just sort them all, and then partition (Thanks @Eric Duminil):

[1, 2, 3, 4, 5, 6].sort.partition(&:odd?).inject(:concat)
#=> [1, 3, 5, 2, 4, 6]

Ruby elegant way of adding all even or odd indexed digits of a number?

number.to_s.chars.map(&:to_i).             # turn string into individual numbers
partition.with_index { |_, i| i.odd? }. # separate the numbers into 2 arrays
map { |a| a.reduce(:+) } # sum each array
#=> [18, 28]

ruby method returns wrong elements with odd/even index ruby 2.6.0

The problem with your actual code is that index returns the index of the first element it finds in the receiver. As 1 is 4 times in number it'll return the index of the first 1 in number from left to right, same for all other repeated numbers.

An easy solution; use each_with_index which allows you to iterate over each element in the receiver plus yielding the current index of that element, so you can check if the index is even or not, deciding where to push the element:

array_of_chars.each_with_index do |x, index|
if index.even?
array_even_index << x
else
array_odd_index << x
end
end

Or you can use partition plus with_index for that:

array_even_index, array_odd_index = 5169294814153321.digits.reverse.partition.with_index { |_, index| index.even? }
p array_even_index # [5, 6, 2, 4, 1, 1, 3, 2]
p array_odd_index # [1, 9, 9, 8, 4, 5, 3, 1]


Related Topics



Leave a reply



Submit