Techioz Blog

マップに続く異なる型を格納する Ruby 配列

概要

方程式を文字列の配列として受け取り、既知の変数をその値に置き換える関数があります(putsステートメントはデバッグ用にのみ含まれています)。

  def replace_known_variables
    @equation_array.map! do |x|
      for known_var in @known_variables
        puts "@equation_array is initially #@equation_array"
        if known_var.full_name == x
          x = known_var.value.to_f
          puts "x is now #{x}"
        else
          x = x
          puts "x is still #{x}"
        end
      end
    end
    puts "@equation_array is now #@equation_array"
  end

これはおそらくこの状況に対処するための「Ruby の方法」ではないので、どんなアドバイスでも歓迎しますが、私の質問は、これを実際に実行すると、x が適切に設定されているように見えますが、結局のところ、私の @ はquation_array は、私が期待する文字列ではなく、known_var (私が作成した Variable クラス) によって使用されるクラスのインスタンスを保持することになります。 x は実際にはインスタンスとして保存されているように見えます。例えば:

@equation_array is initially ["amperage", "*", "resistance"]
x is now 12.0
@equation_array is initially ["amperage", "*", "resistance"]
x is still 12.0
@equation_array is initially [[#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], "*", "resistance"]
x is still *
@equation_array is initially [[#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], "*", "resistance"]
x is still *
@equation_array is initially [[#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], [#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], "resistance"]
x is still resistance
@equation_array is initially [[#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], [#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], "resistance"]
x is now 2200.0
@equation_array is now [[#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], [#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">], [#<Variable:0x000001c28755c490 @abbrev="i", @full_name="amperage", @unit="A", @value="12">, #<Variable:0x000001c28745a060 @abbrev="r", @full_name="resistance", @unit="Ohms", @value="2200">]]

いくつかのこと(すべての代入で to_ タイプを明示的に指定する、値保存で to_f を削除する)を試しましたが、だめで、基本的に何が間違っているのかわかりません(おそらく複雑な方法論は別として)全体)。一時的なハッシュなどを作成することでこれを回避することもできますが、意図したフローの何が問題なのかを理解したいと考えています。

解決策

おそらく、変数名をそれぞれの (浮動小数点) 値にマップするルックアップ ハッシュを構築するでしょう。

@values = @known_variables.to_h { |v| [v.full_name, v.value.to_f] }
#=> {"amperage"=>12.0, "resistance"=>2200.0}

このハッシュを使用すると、置換はほとんど簡単になります。

@equation_array = ['amperage', '*', 'resistance']

@equation_array.map { |x| @values.fetch(x, x) }
#=> [12.0, "*", 2200.0]

Hash#fetch は、最初の引数として指定されたキーの値を返します。キーが見つからない場合 (例: ‘’)、単にキーそのものである 2 番目の引数を返すため、’’ は ’*’ のままになります。