【问题标题】:Generate multi dimensional array from list string从列表字符串生成多维数组
【发布时间】:2017-02-14 12:25:04
【问题描述】:

我想从下面的 PHP 中生成一个多维数组 -

- Item 1
-- Item 1.1
-- Item 1.2
--- Item 1.2.1
--- Item 1.2.2
---- Item 1.2.2.1
- Item 2
- Item 3
- Item 4
-- Item 4.1
-- Item 4.2

我的最终目标是将此字符串转换为无序列表。

我想最好的方法是创建一个递归函数。在美好的一天,我确信我可以解决这个问题,但我脑子里有点空白!

数组结构应该类似于下面的转储 -

array(6) {
  [0]=>
  string(6) "Item 1"
  [1]=>
  array(3) {
    [0]=>
    string(8) "Item 1.1"
    [1]=>
    string(8) "Item 1.2"
    [2]=>
    array(3) {
      [0]=>
      string(10) "Item 1.2.1"
      [1]=>
      string(10) "Item 1.2.2"
      [2]=>
      array(1) {
        [0]=>
        string(12) "Item 1.2.2.1"
      }
    }
  }
  [2]=>
  string(6) "Item 2"
  [3]=>
  string(6) "Item 3"
  [4]=>
  string(6) "Item 4"
  [5]=>
  array(2) {
    [0]=>
    string(8) "Item 4.1"
    [1]=>
    string(8) "Item 4.2"
  }
}

希望你能帮忙。

【问题讨论】:

  • google.com/… // 大部分结果似乎是针对 PHP 的,但是由于您甚至没有提及或标记特定语言,所以我猜那必须这样做。
  • @CBroe 感谢您提供 Google 链接。它是 PHP - 抱歉我忘了包含它,所以现在添加它。这比你的标准字符串递归复杂一点
  • 从上面的cmets,你能提示一下数组应该是什么样子吗?
  • 如果文本总是格式正确,则不需要递归。只需计算每行上的破折号,并使用它来确定何时输出
    标记。有空我会写一个答案。
  • @NirjharLo 我已经更新了我的问题以包含预期的输出。

标签: php arrays recursion


【解决方案1】:

以下内容将直接转换为 HTML,无需递归:

$text = array();
$text[] = '- Item 1';
$text[] = '-- Item 1.1';
$text[] = '-- Item 1.2';
$text[] = '--- Item 1.2.1';
$text[] = '--- Item 1.2.2';
$text[] = '---- Item 1.2.2.1';
$text[] = '- Item 2';
$text[] = '- Item 3';
$text[] = '- Item 4';
$text[] = '-- Item 4.1';
$text[] = '-- Item 4.2';

$previous_dash_count = 0; // topmost parent
foreach ($text as $line) {
    if (preg_match('/(^\-+)(.*)/', $line, $matches, PREG_OFFSET_CAPTURE)===1) {
        $dash_count = strlen($matches[1][0]);
        $title = $matches[2][0];

        if ($dash_count == $previous_dash_count) {
            echo "<li>$title</li>\n";
        } elseif ($dash_count > $previous_dash_count) {
            echo str_repeat("<ul>\n", $dash_count - $previous_dash_count);
            echo "<li>$title</li>\n";
        } else {
            echo str_repeat("</ul>\n",$previous_dash_count-$dash_count+1);
            echo "<ul>\n";
            echo "<li>$title</li>\n";
        }

        $previous_dash_count = $dash_count;
    }
}
echo str_repeat("</ul>\n",$previous_dash_count);

我做了几个假设。输入文本始终表现良好且不包含随机性。另外我不假设 UTF-8 文本,但你可以安全地使用破折号。

这里是所有荣耀的数组版本:

$stack = array();
$previous_dash_count = 0;
$parent_node = array();
foreach ($text as $line) {
    if (preg_match('/(^\-+)(.*)/', $line, $matches, PREG_OFFSET_CAPTURE)===1) {
        $dash_count = strlen($matches[1][0]);
        $title = $matches[2][0];

        if ($dash_count == $previous_dash_count) {
            $parent_node[] = $title;
        } elseif ($dash_count > $previous_dash_count) {
            for ($push_count = $previous_dash_count; $push_count<$dash_count; $push_count++) {
                array_push($stack, $parent_node); // remember node
                $new_child = array();
                $new_child[] = $title;
                $parent_node[] = $new_child;
                $parent_node = $new_child;
            }
        } else {
            for ($pop_count = $previous_dash_count; $pop_count >$dash_count; $pop_count--) {
                $old_child = $parent_node;
                $parent_node = array_pop($stack);
                $parent_node[] = $old_child;
            }
            $parent_node[] = $title;
        }

        $previous_dash_count = $dash_count;
    }
}
for ($pop_count = $previous_dash_count; $pop_count > 0; $pop_count--) {
    $old_child = $parent_node;
    $parent_node = array_pop($stack);
    $parent_node[] = $old_child;
}

print_r($parent_node);

我们保留了一堆数组节点,所以我们在子节点和它的父节点之间有一个链接。请注意,此代码的结构与直接 HTML 版本的结构相同。

【讨论】:

  • 谢谢 - 我最终不得不采用这种方法,因为它是最简单的。技术略有不同,但您的答案仍然正确。干杯!
  • 阵列版也很棒,非常感谢!恭喜:)
  • 就是这样 - 我已经破解了它,但你知道那些日子你真的很难找到解决方案吗?!...
猜你喜欢
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 2012-08-16
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多