缩进列表转换为多维数组

3

我很惊讶在SO(或互联网上)找不到答案。这涉及到一个嵌套的缩进列表,我想将其转换为多维数组,根据缩进级别。

以下是一些示例输入:

Home
Products
    Product 1
        Product 1 Images
    Product 2
        Product 2 Images
    Where to Buy
About Us
    Meet the Team
    Careers
Contact Us

理想情况下,我希望将其输入到某个(递归?)函数中,并获得以下输出:
array(
    'Home' => array(),
    'Products' => array(
        'Product 1' => array(
            'Product 1 Images' => array(),
        ),
        'Product 2' => array(
            'Product 2 Images' => array(),
        ),
        'Where to Buy' => array(),
    ),
    'About Us' => array(
        'Meet the Team' => array(),
        'Careers' => array(),
    ),
    'Contact Us' => array(),
);

我对执行此任务所需的逻辑感到困惑,希望能得到帮助。


5
列表是如何缩进的:制表符 || 空格 || HTML ... - T I
似乎可以将缩进方法(例如作为字符串)传递给构建此数组的函数。 - WWW
4个回答

14

由于仍然不清楚您是正在尝试从某个给定的结构(HTML-DOM)中读取还是从给定的字符串作为纯文本中读取,因此我假设您正在尝试解析字符串。如果是这样,请尝试:

<?php
$list =
'Home
Products
    Product 1
        Product 1 Images
    Product 2
        Product 2 Images
    Where to Buy
About Us
    Meet the Team
    Careers
Contact Us';

function helper($list, $indentation = '    ') {
  $result = array();
  $path = array();

  foreach (explode("\n", $list) as $line) {
    // get depth and label
    $depth = 0;
    while (substr($line, 0, strlen($indentation)) === $indentation) {
      $depth += 1;
      $line = substr($line, strlen($indentation));
    }

    // truncate path if needed
    while ($depth < sizeof($path)) {
      array_pop($path);
    }

    // keep label (at depth)
    $path[$depth] = $line;

    // traverse path and add label to result
    $parent =& $result;
    foreach ($path as $depth => $key) {
      if (!isset($parent[$key])) {
        $parent[$line] = array();
        break;
      }

      $parent =& $parent[$key];
    }
  }

  // return
  return $result;
}

print_r(helper($list));

演示:http://codepad.org/zgfHvkBV


0

我不会写递归函数,但是可以指导你一个有用的方向,看一下PHP的substr_count函数。基于这个函数,你可以计算每行前面制表符的数量,并将其与前一行的制表符数量进行比较,以确定它是子级、同级等。


0

我是唯一一个有美丽思维看到这个模式的人吗?

输入数组几乎就是同样的东西!每行只有三种可能的结尾:开放、整体或闭合括号。

$L = 4;//estimate depth level

function tabbed_text_to_array ($raw, $L) {

        $raw = preg_replace("/^(\\t*)([^\\t\\n]*)\\n?/m" ,  "\t$1'$2' => array(\n" , $raw );

    for( ; $L > 0 ; $L-- ) {

        for( $i=0; $i<3 ;$i++ ) {
            $preL = $L-1;
            $s = array( "^(\\t{{$L}})([^\\t\\),]*)(?=\\n\\t{{$L}}')", "^(\\t{{$L}})([^\\t\\),]*)(?=\\n(\\t{0,{$preL}})')", "^(\\t{{$L}})(\\),)(?=\\n(\\t{{$preL}})[^\t])" );
            $r = array(    "$1$2),"   ,     "$1$2)\n" . str_repeat("\t",$preL) . "),"    ,    "$1),\n$3),"    );
            $raw = preg_replace( "/$s[$i]/m" , $r[$i], $raw );
        }
    }
    return "array(\n". $raw. ")\n);";   

}

此函数生成一个带有文字数组的字符串,然后您只需使用eval()函数即可。虽然看起来不太好,但实际上并不复杂。双反斜杠使得阅读变得困难,但它很简单。

就像细胞复制一样,它首先在一个通道中添加最常见的东西:引号、逗号和开括号,然后在两个通道中添加更小的细节。所有这些都会根据您指定的每个级别运行一次(您可以浪费代码来查找从哪个最深的级别开始处理,但猜测已经足够了)。

请参见工作演示/将制表符缩进文本转换为数组的工具

或者访问php fiddle以查看所有通道,以便您可以扩展此功能。


-3

关于PHP脚本的课程可以满足您的需求。您可以在此处找到它: 数组转列表

它可以将多维数组转换为HTML格式。

更新

实际上需要相反的效果。要做到这一点,最好使用DOMDocument对象,并将HTML加载到对象表示中。

http://php.net/manual/en/domdocument.loadhtml.php


谢谢,但我需要一个能够执行与您所描述的相反操作的脚本。 - Sam Hastings
好的,那么您可能需要将其解析为DOMDocument。请查看loadHTML:http://php.net/manual/en/domdocument.loadhtml.php - Paul Bain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接