循环内循环只运行一次

时间:2016-05-25 19:26:54

标签: php

出于教育目的,我尝试构建PUG Parser。 我有两个循环,一个循环PUG-Code的行,另一个循环unclosed标签,我保存最后一次迭代。

在我的代码中,内部循环似乎只运行一次,因为当我将echo语句用于调试时,我没有获得足够的输出。

foreach ($lines as $line) {
    #Increment the line number
    $lineNum++;

    #Save the current indentation for later use
    $currentIndentation = strspn($line, " ");

    #Go though list of unclosed tags and recursivley close all that need to be closed
    foreach ($unclosed_tags as $lineNum => $tag) {
        #Assign a variable to the tag indentation
        $tagIndentation = $tag[1];

        echo $tag[0] . "$tagIndentation:$currentIndentation=" . !($tagIndentation < $currentIndentation) . "<br>";

        #Check if the current indentation is not smaller than the tag
        if (!($tagIndentation < $currentIndentation)) {
            #Close the tag
            $output .= "</" . $tag[0] . ">";
            #Remove the tag from unclosed list cince we just closed it
            $unclosed_tags = array_diff($unclosed_tags, array($unclosed_tags[$key]));
        }
    }

    #Get the current element (== the first string in a string)
    $currentElement = preg_replace('/(\s*)([^\s]*)(.*)/', '$2', $line);

    #Output as open tag
    $output .= "<" . $currentElement . ">" . trim(str_replace_first($currentElement, "", $line));
    #Add to list of unclosed tags
    $unclosed_tags[$lineNum] = array($currentElement, $currentIndentation);
}

我尝试解析的示例.pug文件如下所示:

html
  head
    title Test
  body
    h1 This page was defined using JADE (PUG)!
    h2 This a Header 2
    div
      p <strong>This text will appear strong</strong>
      hr
      br
    ul
      li This
      li is a 
      li test
    ol
      li <b>Ordered Test</b>
      li for the win

导出的html看起来像这样

<html>
    <head>
        <title>Test</title>

    <body>
        <h1>This page was defined using JADE (PUG)!</h1>
        <h2>This a Header 2</h2>
        <div>
            <p><strong>This text will appear strong</strong></p>
            <hr/>
            </p>
            <br/>
            </p>
            <ul>
                <li>This</li>
                <li>is a</li>
                <li>test</li>
                <ol>
                    <li><b>Ordered Test</b></li>
                    <li>for the win</li>

来自关闭未关闭标签的公寓这是我的完整算法,但它不起作用,因为有时标签没有关闭,因为内循环无法检查是否需要在此循环中关闭更多标签!

我不是在寻找现有的库,而是提示我的代码无效的原因以及如何提高代码质量和执行时间!

3 个答案:

答案 0 :(得分:1)

所以我发现了一些有用的东西。以下是代码示例,我将解释以下更改:

$unclosed_tags

好的,所以改变是:

  1. 我改变了你添加到for的方式,只是一个直接追加。您不需要跟踪此处的行号,这样我们就可以使用$unclosed_tags循环作为内循环。
  2. 我将内循环更改为for循环。原因是您要以相反的顺序关闭标记。当您打开标签时,您希望以相反的顺序关闭它们。
  3. 我将array_diff更改为循环中当前键的简单取消设置。通过反向循环,我们还可以在中断时停止循环,一旦我们完成当前缩进级别的结束标记。
  4. 之后,唯一剩下的就是以相反的顺序循环其余的foreach(array_reverse($unclosed_tags) as $i=>$line){ ...并关闭它们。我想你也可以保留行号和{{1}}与for循环相同的结果。

答案 1 :(得分:0)

中断会让你脱离foreach循环,它不会跳过你到循环中的下一个实例。因此,在这种情况下,您可以删除 else 语句,如果它与 if 不匹配,则只会执行任何操作。

如果您的中断是有意的,那么您将无法在$ unclosed_tags变量中正确地预期/处理数据。

答案 2 :(得分:0)

我制定了一个解决方案。最有可能的问题是由于错误声明的数组访问器。

foreach ($lines as $line) {
    #Increment the line number
    $lineNum++;

    #Save the current indentation for later use
    $currentIndentation = strspn($line, " ");

    print_r($unclosed_tags);

    #Go though list of unclosed tags and recursivley close all that need to be closed
    foreach ($unclosed_tags as $tagIndentation => $tag) {
        #Check if the current indentation is not smaller than the tag
        if (!($tagIndentation < $currentIndentation)) {
            #Close the tag
            $output .= str_repeat(' ', $tagIndentation) . "</" . $tag . ">\n";
            #Remove the tag from unclosed list cince we just closed it
            unset($unclosed_tags[$lineNum]);
        }
    }

    #Get the current element (== the first string in a string)
    $currentElement = preg_replace('/(\s*)([^\s]*)(.*)/', '$2', $line);
    #Output as open tag
    $output .= str_repeat(' ', $currentIndentation) . "<" . $currentElement . ">" . trim(str_replace_first($currentElement, "", $line)) . "\n";
    #Add to list of unclosed tags
    $unclosed_tags[$currentIndentation] = $currentElement;
}
#Close all remaining unclosed tags

这是工作代码。

随意在您的项目中使用它(尽管注意StackOverflows License