A method that doesn't change its arguments

At the moment I’m doing something like this:

def some_method(array1)

array2 = array1.clone

array2.delete_at(i)

return array2

end

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called. Is there a more
elegant solution?

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called.

If your code is slow, it’s not because of this use of clone. If your
code isn’t, don’t bother.

lith wrote:

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called.

If your code is slow, it’s not because of this use of clone. If your
code isn’t, don’t bother.

“Inefficient” can also refer to memory. If the array has 4 million
entries, to copy it 100 times might be considered inefficient in that
sense.

How about something like this:

class MyArray
include Enumerable

def MyArray.init(arr)
@@arr = arr
end

def initialize
@deleted = {}
end

def delete_at(i)
@deleted[i] = true
end

def each
@@arr.each_with_index do |elmt, i|
next if @deleted[i]
yield elmt
end
end

def get_arr
out = []

@@arr.each_with_index do |elmt, i|
  next if @deleted[i]
  out << elmt
end

out

end
end

MyArray.init [“banana”, “strawberry”, “apple”]
data1 = MyArray.new
data2 = MyArray.new

data1.delete_at(0)
data2.delete_at(1)

p data1.get_arr
puts “------”
p data2.get_arr
puts

search1 = data1.select do |elmt|
elmt.length > 5
end
p search1

puts “Found apple.” if data2.include? “apple”

–output:–
[“strawberry”, “apple”]

[“banana”, “apple”]

[“strawberry”]
Found apple.

“Inefficient” can also refer to memory. If the array has 4 million
entries, to copy it 100 times might be considered inefficient in that
sense.

Well, maybe you shouldn’t use an array then anyway – which is more or
less what you’re doing by introducing a layer of indirection.

BTW how does your approach behave if you delete 4 million from
MyArray? I’d rather go for something tree-like and exchange selected
branches, I guess.

On Sun, Nov 8, 2009 at 7:40 PM, Timo J. [email protected] wrote:

end

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called. Is there a more
elegant solution?

Couldn’t you do something like this?

arr1 = (“a”…“j”).to_a
i = 3
p arr1[0…i]+arr1[i+1…-1] #> [“a”, “b”, “c”, “e”, “f”, “g”, “h”,
“i”, “j”]

Harry

On Nov 8, 3:38Â am, Timo J. [email protected] wrote:

end

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called. Â Is there a more
elegant solution?

Could you clarify what you’re trying to do? What you’ve shown is a
method that takes an array and then returns a slightly modified
version. If you don’t want the original to be modified, what’s your
other option?

Are you aware that array duplication is a ‘shallow’ operation? All
you’re doing is (efficiently) copying a list of references to objects,
not the objects themselves. As lith ≈wrote, avoid premature
optimization. You may be spending your time and ours on a complete non-
issue.

On Sun, 08 Nov 2009 19:40:08 +0900, Timo J. wrote:

end

I would like array1 to remain unchanged. It seems a little inefficient
to clone array1 every time some_method is called. Is there a more
elegant solution?

If you’re comfortable with the idea of using completely immutable lists,
and not changing any of the elements of the list, an implementation of
efficiently catenable lists (such as that described in “Purely
Functional
Data Structures”) might be in order.

On Sun, Nov 8, 2009 at 6:38 AM, lith [email protected] wrote:

Arrays in Ruby get unbearably slow when you get into the millions, it
would
definitely be worth considering alternative implementations at that
point.

require ‘benchmark’

def remove_1millionth_index(old_ary)
new_ary = old_ary.clone
new_ary.delete_at 1_000_000
new_ary
end

ary = Array(1…4_000_000)

Benchmark.bm do |b|
b.report {
100.times do
remove_1millionth_index ary
end
}
end

================= output =================

user system total real

7.875000 0.938000 8.813000 ( 8.984000)