Нечетные (или четные) записи в массиве Ruby
есть ли быстрый способ получить все остальные записи в массиве в Ruby? Либо нечетные, либо четные значения записей с 0, включенными в нечетные. Я хотел бы иметь возможность использовать его так:
array1 += array2.odd_values
или
puts array2.odd_values.join("-")
обновление
Это дает именно то, что я после но я уверен, что есть более короткая версия.
array1.each_with_index do |item,index|
if (index %2 ==0) then
array2.push(item)
end
end
21 ответ:
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"]
Итак, по просьбе
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
...
arr = ["0", "1", "2", "3"] arr.select.each_with_index { |_, i| i.odd? } arr.select.each_with_index { |_, i| i.even? }
Как floum указал, что в Ruby 2.2 вы можете просто сделать:
arr.select.with_index { |_, i| i.odd? }
вы можете просто использовать это:
(1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
из Ruby docs: Ruby Docs Reference
какой-то сумасшедший способ использования фасетов:
require 'facets' array = [1,2,3,4,5] odd = array.to_h.keys # 1,3,5 even = array.to_h.values.compact # 2,4
Это, вероятно, никогда не будет прочитано, но...
простой и чистый:
array2.map{ |n| n if n % 2 == 0 }.compact # evens array2.map{ |n| n if n % 2 == 1 }.compact # odds
просто нашел еще более лаконичный способ (должен любить Руби):
array2.find_all{ |n| n % 2 == 0 } # evens array2.reject { |n| n % 2 == 0 } # odds
dst = [] array.each_slice(2) { |x| dst.push(x[1]) }
должен дать вам массив нечетных индексов.
заменить
x[1]
Сx[0]
для записи.
Для справки:
a = [1,2,3,4,5,6] h = Hash[*a] evens = h.keys odds = h.values
Я использую оператор 'splat' массива, чтобы получить значения, разделенные запятыми, и передать их хэшу, который принимает аргументы как переменные ключи/значения.
еще один способ подумать об этом (добавляет array2 evens к array1):
array1 << array2.values_at(*Array.new(array2.size/2){|i| i*2})
Это кажется самым рубиновым решением, сочетающим в себе лучшие подходы Якобма и Гленна Джекмана.
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
здесь код это предназначено для добавления метода select_with_index к Enumerable, что позволит вам сделать
array.select_with_index{|item, i| item if i % 2 == 0}
для эвенов
array.select_with_index{|item, i| item if i % 2 == 1}
на коэффициент
мой взгляд на проблему, определяя простые расширения массива:
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 # => []
Это может работать для вас, или опять же, нет :-)
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]
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]
конечно, учитывая 0 нечетный индекс создает немного hackery, не так ли? Поскольку у вас будут соседние записи, которые по сути являются нечетными индексами. Чтобы компенсировать это, вы можете просто добавить нулевую запись в результат первого сбора. Рассмотрим:
[a[0]] + (1...a.size).step(2).collect { |i| a[i] } => [0, 1, 3, 5, 7, 9]
вы всегда можете сжать это дальше и сделать что-то вроде:
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]
тот же хак доступен для обработки нулевой записи.
С пустым массивом
A
, и полным наборомH
, что-то вроде этого должно работать:H.size.times do |i| if i % 2 == 1 A[i/2] = H[i] end end
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"
Я просто повторно использовал подход, который я использовал для другого вопроса о массивах. : D