0

I need to dynamically retrieve a slice of size 3 from an array (as part of a more complex method):

a = %w(a b c d e)
i = 0 # i is an argument, I need [nil, "a", "b"]
a[(i-1)..(i+1)]
=> [] # no luck
a[(i-1), 3]
=> ["e"]

I know that when code gets messed up, it's not ruby's fault, is mine. What I'm missing? Is there a better way to achieve this?

I need to clarify. What I want is a slice of a given size, around a given index, and maping to nil if the slice goes beyond offset.

2
  • 'around a given index' ? if i=0, what do you expect? ['a', 'b','c'] ? or ['a', nil, nil]? why your expect is ['e', nil, nil]? Commented Feb 28, 2013 at 3:39
  • I think I've been clear enough, given an index(ì), I want to return [a[i-1],a[i],a[i+1]], with nil if index goes offset or negative, that's what I mean with 'around'. The problem is that ruby doesnt return nil on negative indexes. Commented Feb 28, 2013 at 11:32

4 Answers 4

2

Here's a compact way you can do this. It relies on the fact that indexing beyond an array returns nil.

>> i = 0; 3.times.map{|j| a[j+i]}
=> ["a", "b", "c"]
>> i = 4; 3.times.map{|j| a[j+i]}
=> ["e", nil, nil]
Sign up to request clarification or add additional context in comments.

Comments

0

Is each_slice the method you are looking for? Otherwise try to provide a better example for what you actually want to achieve.

1 Comment

each_slice accepts no starting point and retrieves a smaller slice if a.size % 3 != 0, i.e.: (a.each_slice(3).to_a => [["a", "b", "c"], ["d", "e"]]), not what I'm looking for.
0

Enumerable#each_cons will do the trick:

a.each_cons(3){|slice| p slice }

output:

["a", "b", "c"]
["b", "c", "d"]
["c", "d", "e"]

Comments

0

This is how I made it (having to go around ruby indexing negative values):

a = %w(a b c d e)
def slice_around(ary, index)
  slice_3 = ->(x){ x == 0 ? [ary.size+1,0,1] : ((x-1)..(x+1)).to_a }
  idxs = slice_3.call(index).map { |i| ary[i] }
end

> slice_around a, 0
=> [nil, "a", "b"]
> slice_around a, 2
=> ["b", "c", "d"]

It wont work if a negative index is passed though.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.