質問

I have a class called Team. I am trying to create many instances of it and call them team1, team2, etc. I am trying something like

for x in (1..20)
  instancename="team#{x}"
  instancename=Team.new
end

I am getting the memory address of the string like "Team:0x007f949b01d3f8". I assume I have to use instance_variable_set, but I'm having a hard time figuring out the syntax.

役に立ちましたか?

解決

TL;DR

You can do what you want with Kernel#eval or Object#instance_variable_set. You can also generate collections directly. If your needs are much more complex, then you may want to think about alternative data structures.

Using Eval

You are partly on the right track in that you need to define the variables in the current scope. While there are a number of ways to do this, the following will work:

Team = Struct.new :foo
for x in (1..20) do
  eval "\@team#{x} = Team.new"
end

This creates your instance variables:

@team20
#=> #<struct Team foo=nil>

using interpolation.

Interpolation Without Eval

There are alternatives to Kernel#eval, of course, like Object#instance_variable_set. Consider this example:

Team = Struct.new :foo
(1..20).each { |i| instance_variable_set "@team#{i}", Team.new }

I can't really see how it makes much difference in your particular case, but this allows you to avoid #eval while still doing interpolation of the variable name.

Use a Collection

Since I can't imagine how you would use this as anything other than a collection anyway, you might as well just create a collection in the first place. For example:

Team = Struct.new :team_id
teams = (1..20).map { |i| Team.new i }
teams[9]
#=> #<struct Team team_id=10>

You can even find teams in your collection by some value, if you prefer. For example:

teams.select { |t| t.team_id == 10 }
#=> [#<struct Team team_id=10>]

None of this requires a unique variable name. You can use array position or object attributes instead, if you really need to distinguish them.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top