0

在下面的代码中,我的期望是:key2:key5"1"由于第二条elsif语句而被分配,但似乎我的代码运行的是最后一条else语句。我的break陈述没有放在正确的位置吗?

每当运行此代码时,我只希望它替换一个值并结束。

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 |x|
if hash.values_at(*x).count("1") == 2 and hash.values_at(*x).count("3") == 1
    x.each do |x|
        if hash[x] == "3"
            hash[x] = "1"
        break
        end

    end
    break

    elsif hash.values_at(*x).count("2") == 2 and hash.values_at(*x).count("3") == 1
        x.each do |e|
            if hash[e] == "3"
                hash[e] = "1"
            break
            end

        end
        break
     elsif hash.values_at(*x).count("1") == 1 and hash.values_at(*x).count("3") == 2
        x.each do |g|
            if hash[g] == "3"
                hash[g] = "1"
            break
            end
        end
        break
     elsif hash.values_at(*x).count("3") == 3
        x.each do |h|
            if hash[h] == "3"
                hash[h] = "1"
                break
            end
        end
        break

else

end
end
4

3 回答 3

1

这是用更好的空格重新组织的代码:

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 可以完成,但我会留给你来解决。

于 2013-10-04T23:05:23.370 回答
0

除了"3"在您的散列中没有其他值,因此除了最后一个条件之外,您的任何条件最初都不会成功elsif,因为它们都需要存在除"3". 在 last 的主体中elsif,您重新定义hash[key1]为 be "1",但随后您break脱离了内部each,然后break脱离了外部,终止了执行。没有其他事情发生。

于 2013-10-04T22:23:51.900 回答
0

那是一些......有趣的代码。我绝对建议简化以帮助调试,但这就是正在发生的事情。

  1. 进入array.each
  2. elsif hash.values_at(*x).count("3") == 3命中
  3. 你玩一下散列,然后爆发
  4. 你突破array.each
  5. 完毕。

婴儿步,puts电话是你的朋友。

于 2013-10-04T22:34:49.433 回答