より良い空白で再編成されたコードは次のとおりです。
hash = {
:key1 => "3",
:key2 => "3",
:key3 => "3",
:key4 => "3",
:key5 => "3",
:key6 => "3",
:key7 => "3",
:key8 => "2",
:key9 => "3"
}
array = [
[:key1, :key2, :key3],
[:key4, :key5, :key6],
[:key7, :key8, :key9],
[:key1, :key4, :key7],
[:key2, :key5, :key8],
[:key3, :key6, :key9],
[:key1, :key5, :key9],
[:key3, :key5, :key7]
]
array.each do |key_set|
if hash.values_at(*key_set).count("1") == 2 and hash.values_at(*key_set).count("3") == 1
key_set.each do |x|
if hash[x] == "3"
hash[x] = "1"
break
end
end
break
elsif hash.values_at(*key_set).count("2") == 2 and hash.values_at(*key_set).count("3") == 1
key_set.each do |e|
if hash[e] == "3"
hash[e] = "1"
break
end
end
break
elsif hash.values_at(*key_set).count("1") == 1 and hash.values_at(*key_set).count("3") == 2
key_set.each do |g|
if hash[g] == "3"
hash[g] = "1"
break
end
end
break
elsif hash.values_at(*key_set).count("3") == 3
key_set.each do |h|
if hash[h] == "3"
hash[h] = "1"
break
end
end
break
else
end
end
そして、ここでは変数名が改善され、条件の論理グループを視覚的に示すためにいくつかの括弧にand
置き換えられています。&&
array.each do |key_set|
case
when (hash.values_at(*key_set).count("1") == 2) && (hash.values_at(*key_set).count("3") == 1)
key_set.each do |_key|
if hash[_key] == "3"
hash[_key] = "1"
break
end
end
break
when (hash.values_at(*key_set).count("2") == 2) && (hash.values_at(*key_set).count("3") == 1)
key_set.each do |_key|
if hash[_key] == "3"
hash[_key] = "1"
break
end
end
break
when (hash.values_at(*key_set).count("1") == 1) && (hash.values_at(*key_set).count("3") == 2)
key_set.each do |_key|
if hash[_key] == "3"
hash[_key] = "1"
break
end
end
break
when (hash.values_at(*key_set).count("3") == 3)
key_set.each do |_key|
if hash[_key] == "3"
hash[_key] = "1"
break
end
end
break
else
end
end
大量の冗長性と「DRYness」の欠如があります。「DRY」は「Don't Repeat Yourself」の略で、繰り返しの多いコードを減らすことを意味します。
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
break
次の合理的な代替品のように見えます:
key_set.each do |_key|
if hash[_key] == "3"
hash[_key] = "1"
break
end
end
break
これを in に置き換えると、コードは次のようになります。
array.each do |key_set|
case
when (hash.values_at(*key_set).count("1") == 2) && (hash.values_at(*key_set).count("3") == 1)
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
break
when (hash.values_at(*key_set).count("2") == 2) && (hash.values_at(*key_set).count("3") == 1)
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
break
when (hash.values_at(*key_set).count("1") == 1) && (hash.values_at(*key_set).count("3") == 2)
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
break
when (hash.values_at(*key_set).count("3") == 3)
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
break
else
end
end
それぞれwhen
が冗長であるため、上に移動できますcase
。
array.each do |key_set|
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
case
when (hash.values_at(*key_set).count("1") == 2) && (hash.values_at(*key_set).count("3") == 1)
break
when (hash.values_at(*key_set).count("2") == 2) && (hash.values_at(*key_set).count("3") == 1)
break
when (hash.values_at(*key_set).count("1") == 1) && (hash.values_at(*key_set).count("3") == 2)
break
when (hash.values_at(*key_set).count("3") == 3)
break
else
end
end
puts hash
もう少し削減すると、次のようになります。
array.each do |key_set|
_key = key_set.find{ |k| hash[k] == '3' }
hash[_key] = '1' if _key
case
when (hash.values_at(*key_set).count("1") == 2) && (hash.values_at(*key_set).count("3") == 1),
(hash.values_at(*key_set).count("2") == 2) && (hash.values_at(*key_set).count("3") == 1),
(hash.values_at(*key_set).count("1") == 1) && (hash.values_at(*key_set).count("3") == 2),
(hash.values_at(*key_set).count("3") == 3)
break
else
end
end
puts hash
他のすべてと同様に、出力は次のとおりです。
{:key1=>"1", :key2=>"3", :key3=>"3", :key4=>"3", :key5=>"3", :key6=>"3", :key7=>"3", :key8=>"2", :key9=>"3"}
これは、最後のコードが行うことを最初のコードで行うための大量のコードです。さらに、実行できる DRYing は他にもありますが、それを理解するのはあなたに任せます。