A method that doesn't change its arguments

T

Timo Jeranko

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?
 
L

lith

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.
 
7

7stud --

lith said:
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 = true
end

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

def get_arr
out = []

@@arr.each_with_index do |elmt, i|
next if @deleted
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"]
 
H

Harry Kakueki

At the moment I'm doing something like this:

def some_method(array1)
=A0...
=A0array2 =3D array1.clone
=A0...
=A0array2.delete_at(i)
=A0...
=A0return array2
=A0...
end


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

Couldn't you do something like this?

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


Harry
--=20
A Look into Japanese Ruby List in English
http://www.kakueki.com/ruby/list.html
 
L

lith

"Inefficient" can also refer to memory. =A0If 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.
 
P

Phrogz

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?

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.
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

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.
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)
 
K

Ken Bloom

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?

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top