bright-star
bright-star

Reputation: 6447

How to modify an array subset in Ruby iteratively?

I know the idiomatic way to do a for loop in Ruby is to use an Enumerator like .each, but I'm running into a problem: I'd like to iterate over a subset of an Array and modify those elements. Calling .map! with a subset like ary[0..2] or .slice(0..2) doesn't seem to do it; presumably because that slicing operator is creating a new Array?

Desired behavior with for instead of iterator:

iter_ind = [2,3,4]
my_ary = [1,3,5,7,9,11]
for j in iter_ind
  my_ary[j] = my_ary[j] + 1
  # some other stuff like an exchange operation maybe
end
=> [1, 3, 6, 8, 10, 11]

Things that don't work:

irb(main):032:0> ar[2..4].map! {|el| el = el+1}
=> [6, 8, 10]
irb(main):033:0> ar
=> [1, 3, 5, 7, 9, 11]
irb(main):034:0> ar.slice(2..4).map! {|el| el = el+1}
=> [6, 8, 10]
irb(main):035:0> ar
=> [1, 3, 5, 7, 9, 11]
irb(main):036:0> ar[2..4].collect! {|el| el = el+1}
=> [6, 8, 10]
irb(main):037:0> ar
=> [1, 3, 5, 7, 9, 11]

Upvotes: 2

Views: 161

Answers (3)

Stefan
Stefan

Reputation: 114178

You could use Array#each_index if you don't mind referencing the array twice:

ary = [1, 3, 5, 7, 9, 11]
ary.each_index { |i| ary[i] += 1 if i.between? 2, 4 }
#=> [1, 3, 6, 8, 10, 11]

Or if you don't want to iterate the whole array, this would work, too:

ary = [1, 3, 5, 7, 9, 11]
ary[2..4] = ary[2..4].map { |el| el + 1 }
ary
#=> [1, 3, 6, 8, 10, 11]

Upvotes: 1

Nafiul Islam
Nafiul Islam

Reputation: 82470

You may also try the following:

?> ary = [1, 3, 5, 7, 9, 11]
=> [1, 3, 5, 7, 9, 11]

?> ary.map!.with_index {|item, index| index.between?(2, 4) ? item += 1 : item}
=> [1, 3, 6, 8, 10, 11]

?> ary
=> [1, 3, 6, 8, 10, 11]

Upvotes: 1

user2422869
user2422869

Reputation: 760

Try this.

In example below I implemented something that could be named map_with_index. each_with_index if no block given returns iterator. I use it to map our array.

ary = [1, 3, 5, 7, 9, 11]   
ary.each_with_index.map { |elem, index| index.between?(2, 4) ? elem += 1 : elem } 
# => [1, 3, 6, 8, 10, 11]

Upvotes: 2

Related Questions