【问题标题】:Indented list to multidimensional array缩进列表到多维数组
【发布时间】:2012-01-16 13:58:04
【问题描述】:

我很惊讶在 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(),
);

我对执行此类任务所需的逻辑感到困惑,因此我们将不胜感激。

【问题讨论】:

  • 列表如何缩进,制表符 ||空格 || html ...
  • 似乎 indent 方法可以(例如作为字符串)传递给构建这个数组数组的函数。

标签: php


【解决方案1】:

由于尚不清楚您是尝试从某个给定结构 (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

【讨论】:

  • 谢谢你,耀西。完美运行:-)
【解决方案2】:

我不打算编写递归函数,但为了给您指明一个有用的方向,请查看 PHP 的 substr_count 函数。基于此,您可以计算每行前面的制表符数量,并将其与上一行中的制表符数量进行比较,以确定它是子级还是兄弟级等。

【讨论】:

    【解决方案3】:

    我是唯一一个能看到这种图案的人吗?

    输入数组几乎是一样的!,行结束只有 3 种可能的方式:开括号、整括号或右括号。

    $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() 它。 它并不像看起来那么糟糕。双反斜杠使阅读更难,但很简单。

    就像单元格复制一样,它首先在一个过程中添加最常见的东西:引号、逗号和左括号,然后在另外两个过程中添加较小的细节。对于您指定的每个级别,它们都运行一次(您可能会浪费代码来找出开始处理的最深级别,但猜测就足够了。)

    查看工作演示/tool to convert tab-indented text into array

    或访问 php fiddle 并获取所有通行证,以便您对此进行扩展。

    【讨论】:

      【解决方案4】:

      有一个关于 PHP 脚本的类可以满足您的需求。你可以在这里找到它: Array To List

      它需要一个多维数组并创建 HTML。

      更新

      实际上需要与此相反。为此,最好使用 DOMDocument 对象并将 HTML 加载到对象表示中。

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

      【讨论】:

      • 谢谢,但我正在寻找一个可以与您描述的相反的脚本。
      • 哦,好吧,在这种情况下,您可能希望将其解析为 DOMDocument。看看 loadHTML:php.net/manual/en/domdocument.loadhtml.php
      猜你喜欢
      • 2020-10-17
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2013-05-17
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      相关资源
      最近更新 更多