在Ruby中,每个和If语句的行为与我所希望的不同

在Ruby中,每个和If语句的行为与我所希望的不同,ruby,arrays,if-statement,hash,break,Ruby,Arrays,If Statement,Hash,Break,在下面的代码中,我的期望是,由于第二个elsif语句,将:key2或:key5分配给“1”,但是似乎我的代码运行的是最后的else语句。我的break语句是否未放置在正确的位置 每当运行此代码时,我只希望它替换一个值并结束 hash = { :key1 => "3", :key2 => "3", :key3 => "3", :key4 => "3", :key5 => "3", :key6 => "3", :key7 => "3", :key8 =>

在下面的代码中,我的期望是,由于第二个
elsif
语句,将
:key2
:key5
分配给
“1”
,但是似乎我的代码运行的是最后的
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

散列中没有除
“3”
以外的值,因此除了最后一个
elsif
,所有条件最初都不会成功,因为它们都要求存在除
“3”
以外的值。在最后一个
elsif
的主体中,您将
散列[key1]
重新定义为
“1”
,但随后您将
从内部
每个
中断开,然后从外部每个
中断开,终止执行。没有其他事情发生。

这是一些。。。有趣的代码。我当然建议简化以帮助调试,但下面是正在发生的事情

  • 进入
    数组。每个
  • elsif hash.values_在(*x).count(“3”)==3
  • 你玩了一下散列,然后爆发出来
  • 您从
    数组中分离出来。每个
  • 完成了

  • 婴儿步和
    put
    调用在这里是您的朋友。

    以下是您的代码,用更好的空格重新组织:

    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
    
    在这里,它改进了变量名,
    替换为
    &&
    加上一些括号,以直观地显示条件中的逻辑组:

    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”代表“不要重复你自己”,意思是减少重复的代码

    _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
    
    时,每个
    都是冗余的,因此它们可以移动到
    案例的上方

    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"}
    

    第一个程序中有很多代码要做最后一个程序所做的事情。还有,我们可以做更多的干燥工作,但我将让您自己来解决。

    对不起,按8键应该是“2”。然而,当我运行它时:不管怎样,key1总是设置为“1”。这仍然只会给你一个“2”,而不是条件要求的两个,因此结果是一样的。你需要看看
    case
    语句是如何工作的。似乎您正在尝试重新设计
    的工作方式,使其在
    时的行为类似于
    案例
    /
    ,或者可能是嵌套的
    案例
    语句。您还在第6行使用
    x来隐藏外部变量。每个do | x |
    都不是真正要做的事情。
    案例
    会按顺序运行它们吗?我基本上希望它们按顺序运行,如果其中一个键被更改为“1”,那么我希望循环中断@theTinManYes,不要隐藏变量名。对于长度可以超过一个字符的变量名,请使用一些更具描述性的名称。
    case
    将按照与
    if
    相同的顺序运行它们。逻辑从顶部开始,然后通过检查条件来完成。我只是在学习编码,所以我知道它不是最好的。我希望一旦我得到它的工作,我可以折射。谢谢你,我添加了一个
    put
    到第二个
    when
    ,并将键8改为“1”,期待我的
    put
    但是我收到了
    put
    我包括在最后的
    when
    中。编辑:我将检查我的代码,直到它达到最佳性能。@ravensklock-在@TimMan的简化代码中只有一个
    。当你说“final when”时,你指的是什么?在看了这个之后,我明白了我在哪里搞砸了,但我该怎么做,这样它会迭代所有数组
    键集
    ,最后只执行
    (hash.values\u at(*key\u set).count(“3”)==3)
    如果没有一个阵列可以满足上述任何情况,请输入以下代码@铁皮人@petetalfivin