user9503053
user9503053

Reputation: 107

Ruby save modified array in a variable without it changing the original array

I'd like to save in two variables the values of an array excluding the first and last elements.

For example:

prices = [9, 3, 5, 2, 1]

The elements I need are:

prices_excl_first = [3, 5, 2, 1]

prices_excl_last = [9, 3, 5, 2]

I figured out how to remove an element from an array a few ways, including slicing off the value by passing its index to the slice method like so:

first_price = prices.slice(0)
last_price = prices.slice(-1)

We could then save the modified arrays into variables:

array_except_first_price = prices.delete(first_price) #=> [3, 5, 2, 1]
array_except_last_index = prices.delete(last_price) #=> [3, 5, 2]

There are two problems with this:

  1. array_except_last_index doesn't contain the first element now
  2. I still need access to the full, original array prices later

So essentially, how can I just temporarily modify the elements in the array when necessary in the problem?

Slicing and dropping elements from array permanently affect the array.

Upvotes: 1

Views: 790

Answers (5)

Sagar Pandya
Sagar Pandya

Reputation: 9498

Splat it.

*a, d = prices                                                
c, *b = prices

a #=> [9, 3, 5, 2]
b #=> [3, 5, 2, 1]

Upvotes: 2

Stefan
Stefan

Reputation: 114218

You could use each_cons:

a, b = prices.each_cons(prices.size - 1).to_a
a #=> [9, 3, 5, 2]
b #=> [3, 5, 2, 1]

Upvotes: 3

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230481

@Schwern's answer is probably the best you can get. Here's the second best:

prices = [9, 3, 5, 2, 1]
prices[1..-1] # => [3, 5, 2, 1]
prices[0..-2] # => [9, 3, 5, 2]

Or drop/take (which more closely map to the wording of your question).

prices.drop(1) # => [3, 5, 2, 1]
prices.take(prices.size-1) # => [9, 3, 5, 2]

Upvotes: 4

Silvio Mayolo
Silvio Mayolo

Reputation: 70317

You can use dup to duplicate the array before performing destructive operations.

prices = [9, 3, 5, 2, 1]

except_first = prices.dup
except_first.delete_at 0

except_last = prices.dup
except_last.delete_at -1

This does end up duplicating the array a couple of times. If you're dealing with large arrays, this may be a problem.

Upvotes: 1

Schwern
Schwern

Reputation: 165298

Ruby has first and last to copy just the first and last elements.

Ask for the first and last prices.size-1 elements.

prices = [9, 3, 5, 2, 1]
except_first = prices.last(prices.size-1)
except_last = prices.first(prices.size-1)

Upvotes: 6

Related Questions