2017-10-30 3 views
1

ダイナミック変数を作成しようとしていて、フルネームを入力せずに後でそれらを再度使用しようとしています。ルビーで何度もダイナミック変数を使用する方法

players = [1, 2, 3, 4] 

players.each |player| 
    instance_variable_set("@player_#{player}_hand", "foo") 
    instance_variable_set("@player_#{player}_value", "bar") 
} 

puts @player_1_hand # => foo 
puts @player_3_value # => bar 

players.each { |player| 
puts "@player_#{player}_hand" 
} 

# => @player_1_hand 
# => @player_2_hand 
# => @player_3_hand 
# => @player_4_hand 

を次のように私が作ったテストコードがある私は、動的にこれらの変数を呼び出して、および/または更新したいが、私はそれらを初期化した後、私はそれを行う方法がわかりません。私が見つけたドキュメントは、参考になるよりも混乱しています。誰かがこれらを正しく使用する方法を説明できますか?

+0

https://stackoverflow.com/a/18552991/5101493 –

答えて

8

多くのインスタンス変数ではなく各属性に1つのPlayerオブジェクトを作成するというOOPの概念に従うことをお勧めします。あなたはすべてのプロパティのattr_accessor、構造体の代わりにクラスを行いますたいときに、代わりに

@player_1_hand 
@player_3_value 

class Player 
    attr_accessor :number, :hand, :value 
    def initialize(number) 
    @number = number 
    end 
end 

そして

p1 = Player.new(1) 
p2 = Player.new(2) 
p3 = Player.new(3) 
p4 = Player.new(4) 
[p1,p2,p3,p4].each do |player| 
    player.hand = ... 
    player.value = ... 
end 


p1.hand #=> ... 
p1.value #=> ... 
+0

これは正解です。これを適切なRuby形式に変えてくれてありがとう。あなたができることの1つは、イニシャライザがハッシュスタイルのオプション(* kwargs *)やハッシュを取ること、あるいはすべてのフィールドにすばやく入力できるように 'yield self if block_given? 'アプローチを採用することです。 – tadman

+0

また、それぞれに離散変数の代わりにPlayerの配列を持たせ、 'each'で配列を反復することもできます。 – Tom

+1

これらはすべて正しいアプローチですが、単純なPlayerクラスを作成するのは良いスタートです – cmramseyer

2

私はあなたに与えようとしている答えは、あなたが達成しようとしているもののために働くだろうと警告したいが、それについてはあなたがハンマーが必要なときにレンチを使うことに似ている。確かに、レンチが機能するかもしれませんが、私は適切なツールを使用していない配管工を発射します。 instance_variable_getについて

players.each { |p| puts instance_variable_get("@player_#{p}_hand") } 

もっとapidockで見つけることができます。

ただし、一般的には、creating instances of a class以外のインスタンス変数は使用しないでください。しかし、このようなスクリプトの場合は、通常の変数を使用し、インスタンス変数から離れてください。あなたの変数を呼び出すために

2
players = [1, 2, 3, 4] 

players.each { |player| 
instance_variable_set("@player_#{player}_hand", "foo") 
instance_variable_set("@player_#{player}_value", "bar") 
} 

はあなたの変数を更新するにはeval

players.each { |player| 
puts instance_variable_get("@player_#{player}_hand") 
puts instance_variable_get("@player_#{player}_value") 
} 

を使用instance_variable_set再び使用

players.each { |player| 
instance_variable_set("@player_#{player}_hand", instance_variable_get("@player_#{player}_hand") + (player + 5).to_s) 
puts instance_variable_get("@player_#{player}_hand") 
} 

印刷しているすべて:

foo 
bar 
foo 
bar 
foo 
bar 
foo 
bar 
foo6 
foo7 
foo8 
foo9 
+0

どうやっは 'instance_variable_get'を見落としますか?ここでは 'eval'を使う理由は全くありません。それは大規模な過度の攻撃です。 – tadman

+1

@tadmanここで正しさやルビーについては言及していません... OPは質問、特定のものを尋ねました、私は答えを提供しました。私は本当にあなたのポイントを得ることはできません、obviusly私はクラスを使用することができ、すべてのオブジェクトのものは超クールですが、コードはOPTのオブジェクトのいずれかではないので、オブジェクトortientedプログラミングについてはなかった... –

+0

私は平均['instance_variable_get'](https://ruby-doc.org/core-2.4.2/Object.html#method-i-instance_variable_get)が' instance_variable_set'に相当するものとして存在するので、 'eval'は完全にここから外れています'。これらをペアにしてみませんか?それが彼らが意味するものです。あなたが 'eval'を使っているのであれば、本当に良い理由がある方がいいでしょう。ここには絶対に理由はありません。 – tadman

1

Playerクラスで試してみてくださいあなたのためにそれらを自動的に。

Player = Struct.new(:number, :hand, :value) 

players = Array.new 

(1..4).each do |i| 
    player = Player.new(i) 
    player.hand = 'something' 
    player.value = 'blah' 
    players.push player 
end 

players.each do |player| 
    puts "Player #{player.number} has hand #{player.hand} with value #{player.value}" 
end 

出力:

Player 1 has hand something with value blah 
Player 2 has hand something with value blah 
Player 3 has hand something with value blah 
Player 4 has hand something with value blah 
関連する問題