Florent2
Florent2

Reputation: 3513

Array#slice(index, length) that fetches elements at the beginning of the array when index+length is out of range

I'm looking for a compact and readable way to slice an array with an index and a length, but when the index + length is out of range, instead of stopping at the end of the array like

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

I want to get the elements at the beginning of the array:

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

Upvotes: 3

Views: 154

Answers (5)

Like the other one answer using rotate (I used symbol for clarify my answer):

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

Upvotes: 0

BroiSatse
BroiSatse

Reputation: 44675

You can do:

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

Upvotes: 3

ymonad
ymonad

Reputation: 12090

Using Enumerator::Lazy, you can do something like this. Since Enumerable#drop returns an array, you have to use lazy enumerator to handle infinite array. You can use this method if you want to get an array which is wrapped more than once

Works on 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"]

Upvotes: 1

Matt
Matt

Reputation: 20776

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

This handles wrap-around:

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

Upvotes: 1

Gad
Gad

Reputation: 42306

Here is a simple way to do it:

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

Upvotes: 0

Related Questions