Как вы выбираете каждый n-й элемент в массиве? - PullRequest
30 голосов
/ 14 января 2011

Я ищу способ найти в Ruby каждый n-й элемент массива.Например, выбор каждого второго элемента будет преобразовывать:

["cat", "dog", "mouse", "tiger"]

в:

["dog", "tiger"]

Есть ли для этого метод Ruby или есть какой-либо другой способ сделать это?

Я пытался использовать что-то вроде:

[1,2,3,4].select {|x| x % 2 == 0}
# results in [2,4]

, но это работает только для массива с целыми числами, а не со строками.

Ответы [ 8 ]

53 голосов
/ 14 января 2011

Вы можете использовать Enumerable#each_slice:

["cat", "dog", "mouse", "tiger"].each_slice(2).map(&:last)
# => ["dog", "tiger"]

Обновление:

Как уже упоминалось в комментарии, last не всегда подходит, поэтому его можно заменить на first, пропустив первый элемент:

["cat", "dog", "mouse", "tiger"].drop(1).each_slice(2).map(&:first)

К сожалению, это делает его менее элегантным.

ИМО, самым элегантным является использование .select.with_index, которое Накилон предложил в своем комментарии:

["cat", "dog", "mouse", "tiger"].select.with_index{|_,i| (i+1) % 2 == 0}
18 голосов
/ 14 января 2011

Вы также можете использовать шаг:

n = 2
a = ["cat", "dog", "mouse", "tiger"]
b = (n - 1).step(a.size - 1, n).map { |i| a[i] }
5 голосов
/ 14 января 2011

Как насчет этого -

arr = ["cat", "dog", "mouse", "tiger"]
n = 2
(0... arr.length).select{ |x| x%n == n-1 }.map { |y| arr[y] } 
    #=> ["dog", "tiger"]
4 голосов
/ 31 декабря 2013

Вы можете просто использовать метод values_at. Вы можете легко найти это в документации .

Вот несколько примеров:

array = ["Hello", 2, "apple", 3]
array.values_at(0,1) # pass any number of arguments you like
=> ["Hello", 2]

array.values_at(0..3) # an argument can be a range
=>["Hello", 2, "apple", 3]

Полагаю, это решит вашу проблему с "собакой" и "тигром"

array = ["cat", "dog", "mouse", "tiger"]
array.values_at(1,3)

и с другим вашим массивом

[1,2,3,4].values_at(1,3)
=> [2, 4] 
4 голосов
/ 14 января 2011

Еще один способ:

xs.each_with_index.map { |x, idx| x if idx % 2 != 0 }.compact

xs.each_with_index.select { |x, idx| idx % 2 }.map(&:first)

xs.values_at(*(1...xs.length).step(2))
4 голосов
/ 14 января 2011

Если вам это нужно в других местах, вы можете добавить метод к Enumerable:

module Enumerable
   def select_with_index
      index = -1
      (block_given? && self.class == Range || self.class == Array)  ?  select { |x| index += 1; yield(x, index) }  :  self
   end
end

p ["cat", "dog", "mouse", "tiger"].select_with_index { |x, i| x if i % 2 != 0 }

Примечание. Это не мой оригинальный код.Я получил это от здесь , когда у меня была такая же потребность, как и у вас.

3 голосов
/ 16 февраля 2017

Я бы предложил очень простой способ:

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

, например

['a','b','c','d'].select.with_index{ |_,i| i.odd? }
# => ["b", "d"]
3 голосов
/ 10 февраля 2014

Мне нравятся ответы Аншула и Му, и я хочу немного их уточнить и упростить, отправив каждый в виде обезьяньего патча в Enumerable:

Му

module Enumerable
  def every_nth(n)
    (n - 1).step(self.size - 1, n).map { |i| self[i] }
  end
end 

Anshul в

module Enumerable
  def every_nth(n)
    (0... self.length).select{ |x| x%n == n-1 }.map { |y| self[y] }
  end
end 

Тогда с ним очень легко работать. Например, рассмотрим:

a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]

a.every_nth(2)
 => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] 

a.every_nth(3)
 => [3, 6, 9, 12, 15, 18, 21, 24]

a.every_nth(5)
 => [5, 10, 15, 20, 25]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...