【问题标题】:Recursively crawl data folder and create multidimensional array递归爬取数据文件夹并创建多维数组
【发布时间】:2017-05-31 20:32:07
【问题描述】:

所以我有以下情况。在我的项目文件夹中,我有一个包含 .json 文件的“数据”文件夹。这些 .json 文件也是嵌套在文件夹中的。

类似:

/data
    /content
        /data1.json
        /data2.json
    /project
        /data3.json

我想创建一个函数,它可以递归地遍历数据文件夹并将所有 .json 文件存储在一个多维数组中,这样可以相对轻松地添加用于我的项目的静态数据。所以预期的结果应该是:

$data = array(
    'content' => array(
         'data1' => <data-from-data1.json>,
         'data2' => <data-from-data2.json>
    ),
    'project' => array(
         'data3' => <data-from-data3.json>
    )
);

更新

我尝试了以下方法,但这只会返回第一级:

$data = array();
$directoryArray = scandir('./data');

foreach($directoryArray as $key => $value) {
    $data[$key] = $value;
}

有没有一种巧妙的方法来实现这一点?

【问题讨论】:

  • 这离火箭科学还有很长的路要走。您尝试过什么,或者您要报价吗?
  • @RiggsFolly 我已经更新了我的问题。
  • “我已经尝试了以下方法,但这只会返回第一级”——其中的递归在哪里?
  • 这个问题太奇怪了,尤其是当你在上面放了一个 +50 的赏金代表时。如果您只是使用 Google 并稍微考虑一下,这是一项非常容易的任务。

标签: php arrays json recursion multidimensional-array


【解决方案1】:

你应该使用 RecursiveIteratorIterator。跳过一些目录,例如 ... 。在此脚本循环其他子目录之后。

//just to remove extension filename
function removeExtension($filename){
    return preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
}

$startpath= 'data';
$ritit = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($startpath), RecursiveIteratorIterator::CHILD_FIRST);
$result = [];
foreach ($ritit as $splFileInfo) {
    if ($splFileInfo->getFilename() == '.') continue;
    if ($splFileInfo->getFilename() == '..') continue;

    if ($splFileInfo->isDir()){
        $path = [removeExtension($splFileInfo->getFilename()) => []];
    }else{
        $path = [removeExtension($splFileInfo->getFilename()) => json_decode(file_get_contents($splFileInfo->getPathname(), $splFileInfo->getFilename()))];
    }

    for ($depth = $ritit->getDepth() - 1; $depth >= 0; $depth--) {
        $path = [$ritit->getSubIterator($depth)->current()->getFilename() => $path];
    }
    $result = array_merge_recursive($result, $path);
}

print_r($result);

我的 json 文件包含:

  • data1.json: {"foo": "foo"}
  • data2.json: {"bar": "bar"}
  • data3.json: {"foobar": "foobar"}

结果是:

Array
(
    [content] => Array
        (
            [data1] => stdClass Object
                (
                    [foo] => foo
                )

            [data2] => stdClass Object
                (
                    [bar] => bar
                )

        )

    [project] => Array
        (
            [data3] => stdClass Object
                (
                    [foobar] => foobar
                )

        )

)

【讨论】:

  • 感谢 Alexandre,这正是我想要的。我要关闭这个问题,因为太多人误解了我的意思。
  • @KeesvanLierop 到此,您获得了复制和粘贴解决方案,但您仍然不知道如何解决下一个递归问题,因为递归是由 RecursiveIterator 类“在幕后”处理的。
【解决方案2】:

您实际上不必使用RecursiveIteratorIterator。作为程序员,您应该始终知道如何处理递归数据结构,可能是 xml 内容、文件夹树或其他。您可以编写一个递归函数来处理这些任务。

递归函数是调用自身来处理具有多个layersdimensions 的数据的函数。 比如下面的scanFolder函数就是设计用来处理目录内容的,遇到子目录就调用自己。

function scanFolder($path)
{
    echo "scanning dir: '$path'";

    $contents = array_diff(scandir($path), ['.', '..']);
    $result = [];

    foreach ($contents as $item) {
        $fullPath = $path . DIRECTORY_SEPARATOR . $item;

        echo "processing '$fullPath'";
        // process folder
        if (is_dir($fullPath)) {
            // process folder contents
            $result[$item] = scanFolder($fullPath);
        } else {
            // for this specific program, you should perform a check here to see if the file is a json

            // collect the result
            $result[$item] = json_decode(file_get_contents($fullPath));
        }
    }

    return $result;
}

IMO,这是完成这项任务的一种更简洁、更有表现力的方式,我想知道其他人对此声明有何看法。

【讨论】:

  • 我喜欢这个解决方案,因为它展示并教导了如何正确处理递归。不幸的是,OP 只是在寻找一种懒惰的复制和粘贴解决方案,并声称它是他不理解的“火箭科学”。
  • @MarioWerner 我不太高兴发布一些针对经过实战考验的本机功能的手写解决方案。但无论如何我都这样做了,因为我同意你对上述答案的评论主要观点。我也认为如果 OP 在这里提出这个特定问题,他需要了解什么是递归以及如何处理它,而不是节省时间。
【解决方案3】:

我认为你可以使用RecursiveDirectoryIteratorthere is 一个关于这个类的文档。

【讨论】:

  • 这真的只是一个评论。此外,仅链接的答案在此处不受欢迎
  • @RiggsFolly 我怀疑 PHP.net 很快就会被关闭。所以我认为链接到 PHP.net 并没有那么糟糕。
  • 这不仅仅是我评论的链接。即使在最松散的答案描述下,这也不是答案。 这是一条评论,您有足够的代表可以发表评论
  • 整个问题已经很奇怪了。尤其是当 OP 为如此简单的任务提供 +50 赏金代表时。似乎他只想拥有一个现成的复制和粘贴解决方案。如果您提出懒惰的问题,您会得到懒惰的答案。
  • @MarioWerner 好吧,我们不必降低对问题水平的回答。但它绝对是一个为我做的问题
猜你喜欢
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 2010-12-08
  • 2014-10-31
  • 2011-11-13
相关资源
最近更新 更多