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.

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 Sun, Nov 8, 2009 at 7:40 PM, Timo Jeranko <jeranko@gmail.com> wrote:

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?

--
A Look into Japanese Ruby List in English

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 Nov 8, 3:38 am, Timo Jeranko <jera...@gmail.com> wrote:

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.

···

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

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?

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

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.

--
Posted via http://www.ruby-forum.com/\.

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

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)

···

On Sun, Nov 8, 2009 at 6:38 AM, lith <minilith@gmail.com> wrote:

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