Rahul Dess
Rahul Dess

Reputation: 2587

Appending dynamic value to ruby instance variable

I know this code doesn't look good at all , but i just want to explain my requirement. I want to know is there any good or alternative approach to it.

Actually, i want to create a new stack and whenever one stack has reached its capacity. I want to keep track of number of stacks created like @stack_1, @stack_2 ...by incrementing @number += 1 like @stack_@number. And for every stack, i want to maintain a @current_position pointer which is specific to every stack like @stack_2 has @current_position_2. So i want to create dynamic instance variables.

Example:

def initialize
  @number = 1
  @stack+"#{@number}" = Array.new(10)
  @current_position_"#{@number}" = 0
end

Output should be something like @stack1 = Array.new(10).
Lets say if i increment value of @number += 1, it should look like @stack2 = Array.new(10)

Upvotes: 0

Views: 87

Answers (3)

Stefan
Stefan

Reputation: 114138

Instead of creating instance variables to track a stack's state from the outside, you could create a Stack class that tracks its state internally. Here's a very simple one:

class StackOverflow < StandardError; end

class Stack
  def initialize
    @stack = []
  end

  def position
    @stack.size
  end

  def full?
    position == 2 # small size for demonstration purposes
  end

  def push(obj)
    raise StackOverflow if full?
    @stack << obj
  end
end

stack = Stack.new
stack.push "foo"
stack.full?       #=> false

stack.push "bar"
stack.full?       #=> true

stack.push "baz"  #=> StackOverflow

Having a working stack, you can build something like a StackGroup to handle multiple stacks:

class StackGroup
  attr_reader :stacks

  def initialize
    @stacks = [Stack.new]
  end

  def push(obj)
    @stacks << Stack.new if @stacks.last.full?
    stacks.last.push(obj)
  end
end

stack_group = StackGroup.new
stack_group.push "foo"
stack_group.push "bar"
stack_group.stacks.size #=> 1

stack_group.push "baz"  # no error here
stack_group.stacks.size #=> 2

stack_group.stacks
#=> [#<Stack:0x007f9d8b886b18 @stack=["foo", "bar"]>,
#    #<Stack:0x007f9d8b886a50 @stack=["baz"]>]

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110665

You can do it like this:

instance_variable_set("@stack#{@number}", Array.new(10, :a))
@stack1
  #=> [:a, :a, :a, :a, :a, :a, :a, :a, :a, :a]

instance_variable_set("@stack#{@number+1}", Array.new(10, :b))
@stack2
  #=> [:b, :b, :b, :b, :b, :b, :b, :b, :b, :b]

instance_variable_set("@current_position_#{@number}", 0)
@current_position_1
  #=> 0

Upvotes: 1

Raghuveer
Raghuveer

Reputation: 2638

Instead of array I suggest you to use Hash Map

@stack = Hash.new

@stack[@number] = <Your Array>

Be Careful if the @number is same your array will be replaced..

For more information about hash maps http://www.ruby-doc.org/core-1.9.3/Hash.html

Upvotes: 2

Related Questions