2011-01-15 9 views
0

シンボルを使い続けながら、これをRubyで処理するより良い方法はありますか?このタイプの包括的なロジックをRubyで処理する最良の方法は何ですか?

pos = :pos1 # can be :pos2, :pos3, etc. 

if pos == :pos1 || pos == :pos2 || pos == :pos3 
    puts 'a' 
end 

if pos == :pos1 || pos == :pos2 
    puts 'b' 
end 

if pos == :pos1 
    puts 'c' 
end 

明白な方法は、数値定数のシンボルを交換することですが、それはオプションではありません。

pos = 3 

if pos >= 1 
    puts 'a' 
end 

if pos >= 2 
    puts 'b' 
end 

if pos >= 3 
    puts 'c' 
end 

ありがとうございました。

EDIT Rubyがアルファベット順にシンボルを注文したことを知りました。これは完全に機能します。

pos = :pos2 # can be :pos2, :pos3, etc. 

if pos >= :pos1 
    puts 'a' 
end 

if pos >= :pos2 
    puts 'b' 
end 

if pos >= :pos3 
    puts 'c' 
end 
+0

2番目のコードでは、posを数字として扱うとコードが単純化されることが示唆されているようです(表示されているだけでなく、他の場所でも同様です)。 – tokland

+0

'pos 'が':pos1'ならば、a、b、c(と改行)が出力されます。 –

答えて

2

ない、これは......

最善の方法である場合、私は配列からinclude?方法を利用すると確信:

puts 'a' if [:pos1, :pos2, :pos3].include? pos 
puts 'b' if [:pos1, :pos2].include? pos 
puts 'c' if [:pos1].include? pos 
+1

最後の行で 'if pos ==:pos1'を使うだけです。 –

+0

あなたは正しいです、Jordão:D – PeterWong

+0

Hmm ..これは意味があります。それはしかし、それらの配列の参照のオーバーヘッドがあります。 – evets

0

より一般的に、あなたはこれを使用することができます:

pos = :pos3 
arr = [:pos1,:pos2,:pos3] 
curr = 'a' 

idx = arr.length 
while idx > 0 
    puts curr if arr.last(idx).include? pos 
    curr = curr.next 
    idx -= 1 
end 

またはこの、あなたの具体的な例:

puts 'a' 
puts 'b' if pos != :pos3 
puts 'c' if pos == :pos1 
2

だけcaseステートメントを使用

pos = :pos1 # can be :pos2, :pos3, etc. 

case pos 
    when :pos1 then %w[a b c] 
    when :pos2 then %w[a b] 
    when :pos3 then %w[a] 
end.each {|x| puts x } 
+0

それは本当にそれを解決しません。あなたはその中で同じコードを複製する必要があります...あなたは同じコードを実行したいと仮定します。 pos1の場合はXXXを実行しますが、pos1またはpos2の場合はXXXとYYYYを実行します。 – evets

+0

繰り返しが必要です。答えのどれもDRYではありません。私はここで繰り返しの軸を逆転しただけです。なぜなら、このインスタンスではより簡潔で読みやすいように見えるからです。別の組の入力および出力は、異なる構造化を必要とすることがある。 – edgerunner

+1

あなたが使用する解決策の種類は、実際の生活の中に置かれているものに依存します。 DRYは通常は良い考えですが、不変のドグマとして扱うのは馬鹿です。 –

1

あなたの出力を得るためにさまざまな方法がたくさんあります。どれがあなたが を望んでいるかは、あなたのifステートメントに対するあなたの具体的な反対にかかっています。 出力を簡単にするために余分な書式設定を追加しました。 を読むことができます。

あなたは論理的論理和を好きではないと彼らは出力から結果 を分離する方法の場合は、ルックアップテーブルを使用することができます。

puts "Lookup table 1:" 
lookup_table1 = { 
    :pos1 => %w{a b c}, 
    :pos2 => %w{a b }, 
    :pos3 => %w{a }, 
} 
[:pos1, :pos2, :pos3].each { |which| 
    puts "\t#{which}" 
    lookup_table1[which].each { |x| puts "\t\t#{x}" } 
} 

それとも、あなたがすべての「仕事」をしたい場合は、ルックアップテーブル:

puts "Lookup table 2:" 
lookup_table2 = { 
    :pos1 => lambda do %w{a b c}.each { |x| puts "\t\t#{x}" } end, 
    :pos2 => lambda do %w{a b }.each { |x| puts "\t\t#{x}" } end, 
    :pos3 => lambda do %w{a }.each { |x| puts "\t\t#{x}" } end, 
} 
[:pos1, :pos2, :pos3].each { |which| 
    puts "\t#{which}" 
    lookup_table2[which].call 
} 

あなたの問題はシンボルが序数ではないということであるならば、あなたは 文字列に変換することによって、それらをordinalizeことができます。

puts "Ordinals by .to_s and <=" 
[:pos1, :pos2, :pos3].each { |which| 
    puts "\t#{which}" 
    if which.to_s <= :pos3.to_s 
     puts "\t\ta" 
    end 
    if which.to_s <= :pos2.to_s 
     puts "\t\tb" 
    end 
    if which.to_s <= :pos1.to_s 
     puts "\t\tc" 
    end 
} 

それともサルはシンボル クラス(推奨されません)に比較演算子にパッチを当てることができます:

puts "Ordinals by Symbol#<=" 
class Symbol 
    def <= (x) 
     self.to_s <= x.to_s 
    end 
end 
[:pos1, :pos2, :pos3].each { |which| 
    puts "\t#{which}" 
    if which <= :pos3 
     puts "\t\ta" 
    end 
    if which <= :pos2 
     puts "\t\tb" 
    end 
    if which <= :pos1 
     puts "\t\tc" 
    end 
} 

それとも、あなたの序数値を供給するために、ルックアップテーブルを使用することができます。

puts "Ordinals through a lookup table:" 
ordinal = { 
    :pos1 => 1, 
    :pos2 => 2, 
    :pos3 => 3, 
} 
[:pos1, :pos2, :pos3].each { |which| 
    puts "\t#{which}" 
    if ordinal[which] <= 3 
     puts "\t\ta" 
    end 
    if ordinal[which] <= 2 
     puts "\t\tb" 
    end 
    if ordinal[which] <= 1 
     puts "\t\tc" 
    end 
} 

もの私の頭の上から明らかなものです。あなたのifのアプローチの問題点についてもっと詳しく説明しなければ、何が最善であろうと言うのは難しいです。 2番目の例は、本当に欲しいものが記号を序数にする方法であることを示しています。

関連する問題