【问题标题】:for each ... break对于每个 ... 休息
【发布时间】:2010-12-25 18:14:23
【问题描述】:

每次我从 for-each 构造(PHP/Javascript)中“突破”出来时,我都觉得很脏

所以是这样的:

// Javascript 示例

for (object in objectList)
{
   if (object.test == true)
   {
      //do some process on object
      break;
   }

}

对于大型对象列表,我会费力地构建一个更优雅的解决方案。但是对于小型列表,没有明显的性能问题,因此“为什么不呢?”它快速,更重要的是易于理解和遵循。

但它只是“感觉不对”。有点像 goto 语句。

遇到这种情况你是怎么处理的?

【问题讨论】:

  • 我知道你在说什么,但每个人都在正确的轨道上——休息很好,特别是对于小列表。我的大列表通常来自数据库查询,如果我必须使用那里的 LIMIT 函数来只提取记录的子集。简短的回答——不要因为使用“break”或“continue”而感到难过
  • 您的代码不会以这种方式工作,因为 for..in 运算符将始终遍历对象的键(字符串)。你的意思可能是这样的: for (var key in objectList) { var object = objectList[key]; ... }

标签: php javascript foreach


【解决方案1】:

一般来说break 语句没有问题。但是,如果像这样的块出现在代码库的不同位置,您的代码可能会成为问题。在这种情况下,break 语句是重复代码的小代码。

您可以轻松地将搜索提取到可重用的函数中:

function findFirst(objectList, test)
{
  for (var key in objectList) {
    var value = objectList[key];
    if (test(value)) return value;
  }
  return null;
}

var first = findFirst(objectList, function(object) {
  return object.test == true;
}
if (first) {
  //do some process on object
}

如果你总是以某种方式处理找到的元素,你可以进一步简化你的代码:

function processFirstMatch(objectList, test, processor) {
  var first = findFirst(objectList, test);
  if (first) processor(first);
}

processFirst(
  objectList,
  function(object) {
    return object.test == true;
  },
  function(object) {
    //do some process on object
  }
}

因此,您可以利用 JavaScript 中功能特性的强大功能,让您的原始代码更具表现力。作为副作用,这会将break 语句从常规代码库中推送到辅助函数中。

【讨论】:

    【解决方案2】:

    看,休息并没有困扰我。编程构建在 goto 之上,for-break 与所有控制结构一样,只是 goto 的一种特殊形式,旨在提高代码的可读性。 永远不要因为编写可读代码而感到难过!

    现在,我确实对与true 的直接比较感到肮脏,尤其是在使用类型转换相等运算符时...哦,是的。你写的 - if (object.test == true) - 相当于写 if (object.test),但需要更多的思考。如果您真的希望只有在object.test 既是布尔值 true 时该比较才能成功,那么您将使用the strict equality operator (===)...否则,跳过它。

    【讨论】:

    • 关于“== true”的事情很好。我总是想建议人们使用“if ((object.test == true) == true)”,只是为了看看他们是否知道它有多荒谬。
    【解决方案3】:

    我的偏好是简单地使用break。它很快,通常不会使事情复杂化。

    如果您使用forwhiledo while 循环,您可以使用变量来确定是否继续:

    for ($i = 0, $c = true; ($i < 10) && $c; $i++) {
        // do stuff
    
        if ($condition) {
            $c= false;
        }
    }
    

    打破foreach 循环的唯一方法是使用breakreturn

    【讨论】:

    • 我这样做了,但通常只使用while 循环。
    • 所以你宁愿添加一个标志、五行和&amp;&amp; 而不是break;?
    • 这可能不是更好的解决方案,但至少它是另一种方法;)
    • 我从未声称添加另一个变量是我的偏好。这是一种选择。
    • 我不确定您的回答是否值得投反对票。我对您所写内容的唯一问题是,它实际上并不允许您迭代对象的关联数组,这往往是问题出现的时候。
    【解决方案4】:

    使用一个

    Object object;
    int index = 0;
    
    do
    {
        object = objectList[index];
        index++;
    }
    while (object.test == false)
    

    如果打破for 循环让你感到不安。

    【讨论】:

    • 假设是数字索引。
    • 将想法扩展到任何类型的索引,只要它可以枚举并且有一种方法可以从一个项目转到下一个项目。
    【解决方案5】:

    中断和继续不是 goto。他们在那里是有原因的。完成循环结构后,退出循环

    现在,我要避免的是非常非常深的嵌套(也就是箭头设计反模式)。

    if (someCondition)
    {
        for (thing in collection)
        {
            if (someOtherCondition)
            {
                break;
            }
        }
    }
    

    如果您要休息一下,请确保您的代码结构只有一层。使用函数调用使迭代尽可能浅。

    if (someCondition)
    {
        loopThroughCollection(collection);
    }
    
    function loopThroughCollection(collection)
    {
        for (thing in collection)
        {
            if (someOtherCondition)
            {
                doSomethingToObject(thing);
                break;
            }
        }
    }
    
    function doSomethingToObject(thing)
    {
        // etc.
    }
    

    【讨论】:

    • 曾几何时,当我开始编程时,我有一个非常酷的用于密码检查的嵌套 if 语句 .... :)
    【解决方案6】:

    它很快,更重要的是易于理解和遵循。

    不要因为休息而难过。 Goto 不受欢迎,因为它很快,更重要的是不容易理解和遵循。

    【讨论】:

      【解决方案7】:

      也许我误解了您的用例,但为什么要中断呢?我假设您希望测试对于列表中的最多一个元素是正确的?

      如果没有性能问题并且您想清理代码,您可以随时跳过测试和中断。

      for (object in objectList)
      {
        //do some process on object
      }
      

      这样,如果您确实需要对多个元素执行该过程,您的代码就不会中断(双关语)。

      【讨论】:

      • 我只会打破我想找到第一个(或唯一一个)项目以匹配我的测试子句的情况。在这些情况下,简单地让循环继续只是燃烧循环。
      • 这取决于你更关心的是烧脑周期还是 CPU 周期。 Breaking 是一种优化——它可能是一个合理的优化,但如果列表很小,那么可以考虑将其排除在外,直到你知道你需要它为止。
      【解决方案8】:

      它的意思是像它一样。 Break 旨在跳出循环。如果你在循环中找到了你需要的东西,为什么还要继续循环呢?

      【讨论】:

        【解决方案9】:

        我认为它更易于阅读,因此更易于维护。

        【讨论】:

          【解决方案10】:

          就像你说的““为什么不呢?”它很快,更重要的是易于理解和遵循。”

          为什么觉得脏,我看不出有什么问题。

          【讨论】:

            【解决方案11】:

            对于小型列表,这样做没有问题。 正如您所提到的,您可能想为大型列表(尤其是大小未知的列表)考虑一个更“优雅”的解决方案。

            有时感觉不对,但没关系。你会及时学会爱break

            【讨论】:

            • 我不知道....我已经编程了大约 15 年。我这样做(使用休息时间),有时看起来像是在作弊......
            【解决方案12】:

            我会使用break 声明。

            【讨论】:

              【解决方案13】:

              我真的看不出跳出 for 循环有什么问题。除非你有某种哈希表、字典,你有某种键来获取值,否则真的没有其他方法。

              【讨论】:

                【解决方案14】:

                我使用休息时间。这是一个完美的解决方案。

                【讨论】:

                • 我喜欢“cromulent”的地方在于它意味着它是什么——一个从上下文中非常明显的词。
                • 通过该论点,您可以通过删除单词并留下上下文来进一步澄清句子。也节省字节!
                • @Leigh:“这是一个完美的解决方案”?
                • 我接受你的回答纯粹是为了教我一个新的,尽管是流行的词。
                • 我很高兴能扩大您的词汇量。
                猜你喜欢
                • 2017-02-02
                • 1970-01-01
                • 2020-02-15
                • 1970-01-01
                • 2016-01-23
                • 1970-01-01
                • 2018-05-20
                • 2019-08-25
                • 1970-01-01
                相关资源
                最近更新 更多