这是用更好的空格重新组织的代码:
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
存在大量冗余和缺乏“干性”。“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
因此,将代码替换为:
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 可以完成,但我会留给你来解决。