1

最近、Ruby でコーディングするときに、メソッドへの入力に応じて異なる変数を割り当てる必要がある場合、次のようなハッシュを使用しています。

variable = { "option1" => [1,2,3], "option2" => [3,2,1]}[input]

このアプローチで私が最も気に入っている点は、スケーラビリティです。入力は、たとえば 5 つの異なる値の 1 つにすることができますが、これはifステートメントでは少し面倒です。

しかし、これを行うときに何を失うのでしょうか? ハッシュを初期化する必要があるため、より多くのメモリを使用しますか? もっとゆっくり?もっと早く?

比較のために、同等のifステートメントは次のようになります。

variable = Array.new
if input.eql?("option1")
  variable = [1,2,3]
else
  variable = [3,2,1]
end

(はい、?記法を 2 つのオプションに使用できましたが、それ以上は使用できなかったので、構造を比較して示したかったのです。)

4

3 に答える 3

6

さらに 2 つのオプションが表示されます。

使用するcase

case input
when 'option1'
  [1, 2, 3]
else
   # default here or error message 
end

メタプログラミングの使用:

class Foo
  def option1
    [1, 2, 3]
  end

  def option2
    [3, 4, 5]
  end
end

Foo.new.send(input)

ベンチマークは、与えられたすべてのソリューションのパフォーマンスを判断するのに役立ちます. ただし、パフォーマンスは優れていますが、コードの匂い、可読性、再利用性についても注意する必要があります。ハッシュを使用すると、ステートメントよりも柔軟性がありますが、ある時点で実装if elseの限界に達することがあります。hash

caseより読みやすくなりますが、多くの条件がある場合は非常に見苦しくなります...

メタプログラミングは優れており、多くの柔軟性を提供しますが、あなたの場合はやり過ぎかもしれません.

于 2013-07-08T09:39:04.487 に答える
3

私がハッシュ アプローチを好む理由の 1 つは、それがロジックをデータ自体にシフトすることです。さらにルールを追加する場合は、コードではなくデータを変更するだけです。また、外部ソース (構成ファイル、ネットワークなど) からデータをロードできます。要するに:柔軟性

パフォーマンスについて話している場合、これら 2 つのアプローチはほとんど同じです。(実際のアプリで)違いを検出できるとは思えません。

于 2013-07-08T09:37:13.937 に答える
3

ハッシュを使用している場合は、一度定義してください (定数として)。

いくつかのベンチマーク (実行時):

#!/usr/local/bin/ruby -w

require 'benchmark'

def by_hash1(i)
  { "option1" => [1,2,3], "option2" => [3,2,1] }[i]
end

TheHash = { 
  "option1" => [1,2,3], 
  "option2" => [3,2,1],
}
def by_hash2(i)
  TheHash[i]
end

def by_case(i)
  case i
  when 'option1'
    [1, 2, 3]
  when 'option2'
    [3, 2, 1]
  end
end

def by_if(i)
  if i.equal?('option1')
    [1, 2, 3]
  else
    [3, 2, 1]
  end
end

class Foo
  def self.option1
    [1, 2, 3]
  end

  def self.option2
    [3, 4, 5]
  end
end


N = 10_000_000
Inps = %w{ option1 option2 }

Benchmark.bm(10) do | x |
  x.report('by hash1') { N.times { by_hash1(Inps.sample) } }
  x.report('by hash2') { N.times { by_hash2(Inps.sample) } }
  x.report('by case')  { N.times { by_case(Inps.sample)  } }
  x.report('by if')    { N.times { by_if(Inps.sample)  } }
  x.report('meta')     { N.times { Foo.send(Inps.sample) } }
end

与える

                 user     system      total        real
by hash1    11.529000   0.000000  11.529000 ( 11.597000)
by hash2     2.387000   0.000000   2.387000 (  2.401000)
by case      3.151000   0.000000   3.151000 (  3.155000)
by if        3.198000   0.000000   3.198000 (  3.236000)
meta         3.541000   0.000000   3.541000 (  3.554000)

私のルビー2.0.0p195(2013-05-14)[x64-mingw32]。

通常、パフォーマンスはあまり重要ではないと思います。パフォーマンスの問題が発生した場合にのみ、調査を開始する必要があります。それ以外の場合は、読みやすさなどの方が重要です。

于 2013-07-08T09:50:10.470 に答える