Массив#slice (индекс, длина), который извлекает элементы в начале массива, когда индекс длина выходит за пределы диапазона

#ruby

#ruby

Вопрос:

Я ищу компактный и читаемый способ нарезать массив с индексом и длиной, но когда индекс длина выходит за пределы диапазона, вместо остановки в конце массива, например


[ "a", "b", "c", "d", "e" ].slice(4, 3) #=> ["e"]

Я хочу получить элементы в начале массива:


#=> ["e", "a", "b"]

Ответ №1:

Вы можете сделать:

 index = 4
length = 3
[ "a", "b", "c", "d", "e" ].cycle.take(index   length).last(length)
  

Ответ №2:

 a = [ "a", "b", "c", "d", "e" ]
Array.new(3) { |i| a[(i 4)%a.size] }
# => ["e", "a", "b"]
  

Это обрабатывает перенос:

 Array.new(10) { |i| a[(i 4)%a.size] }
# => ["e", "a", "b", "c", "d", "e", "a", "b", "c", "d"]
  

Ответ №3:

Используя Enumerator::Lazy , вы можете сделать что-то вроде этого. Поскольку Enumerable#drop возвращает массив, вам придется использовать отложенный перечислитель для обработки бесконечного массива. Вы можете использовать этот метод, если хотите получить массив, который переносится более одного раза

Работает на ruby 2.1.2 .

 ["a","b","c","d","e"].lazy.cycle.drop(4).take(3).to_a # ["e","a","b"]

["a","b","c","d","e"].lazy.cycle.drop(4).take(6).to_a # ["e","a","b","c","d","e"]
  

Ответ №4:

Вот простой способ сделать это:

 [ "a", "b", "c", "d", "e" ].rotate(4).slice(0, 3) #=> ["e", "a", "b"]
  

Комментарии:

1. Это не работает, когда длина ( 3 в данном случае) превышает длину массива.

2. почему длина должна превышать длину массива? вы вводите перенос, когда это даже не упоминается в задаче.

Ответ №5:

Как и в другом ответе, использующем поворот (я использовал символ для уточнения моего ответа):

 (:a..:e).to_a.rotate(4).first(3) #=> [:e, :a, :b]