2

私はそのような配列に含まれるデータを持っています、

$file['info']['files'] = array(
    [0] => array(
         'length' => (int),
         'path' => array (
              [0] => 'file.txt',
         ),
    ),
    [1] => array(
         'length' => (int),
         'path' => array (
              [0] => 'directory one',
              [1] => 'file2.txt',
         ),
    ),
    [2] => array(
         'length' => (int),
         'path' => array (
              [0] => 'directory one',
              [1] => 'directory two',
              [2] => 'file3.txt',
         ),
    ),
);

$file['info']['files']配列には、任意の数の要素を含めることができます。各path配列に含まれる$file['info']['files']配列は、私が問題を抱えている場所です。

ファイル構造に関する情報が含まれています。要素が 1 つだけ存在する場合、それはファイルです。複数の要素が存在する場合、上から始まる各要素は次の要素の親フォルダーであり、最後の要素は最後のフォルダー内のファイルです。上記の例を取ると、次のファイル構造になります

FILE file1.txt
FOLDER directory one
     FILE file2.txt
     FOLDER directory two
          FILE {file3.txt}

このデータを次のような独自の配列構造に抽出したいと思います。

 $sortedFiles = array(
     'file1.txt' => (int),
     'directory one' => array(
         'file2.txt' => (int),
         'directory two' => array(
              'file3.txt' => (int),
         ),
     ),
 );

私はこれまでのところこのコードを持っています、

foreach($file['info']['files'] as $file) {
    // LENGTH AND PATH ARE SET
    if(isset($file['length'], $file['path'])) {
        // GET COUNT OF FILE PATH ARRAY
        $count = count($file['path']);
        // SINGLE FILE
        if($count == 1) {
            $sortedFiles[$file['path'][0]] = $file['length'];
        // FILES IN DIRECTORY
        } else {
            // BUILD ARRAY STRUCTURE FOR DIRECTORIES
        }
    }
}

アレイにディレクトリを追加するときに問題があります。手動で行うことができ、ディレクトリの配列が存在するかどうかを確認し、存在しない場合は作成し、存在する場合は追加するたびに、非常に多くのディレクトリをダウンさせることができます。以下のコードでこれを試しましたが、1ディレクトリの深さしかありません(コードは// BUILD ARRAY STRUCTURE上記の場所に行きました)。

// FOLDER NOT SET
if(!isset($files[$file['path'][0]])) {
    $sortedFiles[$file['path'][0]] = array($file['path'][1] => $file['length'],);
// FOLDER SET
} else {
    $sortedFiles[$file['path'][0]][$file['path'][1]] = $file['length'];
}

存在する各ディレクトリの配列を動的に作成し、必要な情報を追加するにはどうすればよいでしょうか?ディレクトリ構造が何レベルも深くなる可能性があることを念頭に置いてください。

私のかなり長い質問を読んでくれてありがとう。誰かが私にくれた助けに感謝します。

4

4 に答える 4

3

以下の例のように、関数を再帰的に呼び出す必要があります。

function get_contents_dir( $dir )
{
    $names = array();

    if ( is_dir($dir) && is_readable($dir) )
    {
            foreach ( scandir($dir) as $file )
            {
                    if ( is_dir($dir."/".$file) && is_readable($dir."/".$file) )
                    {
                            $names[] = get_contents_dir($dir."/".$file);
                    }

                    if ( is_file($dir."/".$file) && is_readable($dir."/".$file) )
                    {
                            $names[] = $dir."/".$file;
                    }
            }
    }

    return $names;
}

この関数は、最初に設定されたフォルダーを開き、$dirファイルのリストをスキャンして、見つかった各ファイルを配列に追加します。これは、フォルダーをスキャンした後return、関数の戻り値として編集されます。

scandir()結果のエントリ (フォルダー内のファイルとフォルダーのリスト) が実際にはフォルダーである場合にねじれが発生します。その場合、関数はその内部から再帰的に呼び出され ($names[] = get_contents_dir($dir."/".$file);関数内から関数を呼び出している行を参照)、サブフォルダーにもインデックスが作成されます。すべてのサブフォルダーのインデックスが作成されるまで、すすいで繰り返します。

関数を呼び出して実行すると、配列が返されます。配列の各キーがエントリになります。ファイルの場合、キーにリンクされた値はファイルの名前です。フォルダーの場合、値は前の配列にネストされた別の配列になります。

返された配列から取得したダンプの例を次に示します。

array (
  0 => './libmysqlclient.so.16.0.0',
  1 => './libmysqlclient_r.so.16.0.0',
  2 => 
  array (
    0 => './libs/libboost_thread-mt.a',
    1 => './libs/libboost_thread-mt.so.1.38.0',
    2 => './libs/libmysql.dll',
    3 => './libs/libmysqlclient16_5.1.41-3ubuntu12_i386.deb',
  ),
  3 => 
  array (
    0 => './radio_sneaker/cl_auto.lua',
    1 => './radio_sneaker/sh_auto.lua',
    2 => './radio_sneaker/sh_coms.lua',
    3 => './radio_sneaker/sh_info.lua',
    4 => './radio_sneaker/sv_auto.lua',
    5 => './radio_sneaker/sv_hooks.lua',
  ),
  4 => './sv_auto.lua',
)

treeこの出力を、同じフォルダーで実行されたコマンドと比較します。

|   libmysqlclient.so.16.0.0
|   libmysqlclient_r.so.16.0.0
|   sv_auto.lua
|   
+---libs
|       libboost_thread-mt.a
|       libboost_thread-mt.so.1.38.0
|       libmysql.dll
|       libmysqlclient16_5.1.41-3ubuntu12_i386.deb
|       
\---radio_sneaker
        cl_auto.lua
        sh_auto.lua
        sh_coms.lua
        sh_info.lua
        sv_auto.lua
        sv_hooks.lua
于 2012-06-02T20:46:31.500 に答える
1

これをコードに取り込んでもらいますが、重要な教訓は次のとおりです。

フラット配列を入れ子構造に変える

$a = array(
    'dir1', 'dir2', 'file.txt'
);

$structure = array(array_pop($a));
foreach (array_reverse($a) as $dir) {
    $structure = array($dir => $structure);
}

print_r($structure);

ある構造を別の構造にマージする

$result = array_merge_recursive($result, $structure);

マージのためにすべての構造を反復するだけです。

于 2012-06-02T20:16:39.877 に答える
1

joinPHP の関数を使用してパスをマージし、パスが存在するかどうかを確認してみませんか? そうでない場合は、フォルダーが存在するかどうかをレベルごとにチェックし、存在しない場合は作成してさらに移動します。私が言いたいのは、このような動的な構造を作成することは、まず第一に、難しく、台無しになりやすいということです。簡単な道を歩まないのはなぜですか?

于 2012-06-02T20:07:02.680 に答える
1

最初は空で、少しずつ埋められるディレクトリ構造を表す配列があると想像してください。この配列内の「現在の」アイテムを追跡し、ディレクトリ名を反復処理する必要があります。各反復で、現在のアイテムの下にサブ配列が存在しない場合は作成し、現在のアイテムをこのサブ配列に設定します。

これは、再帰または反復のいずれかで実行できます。これは PHP であるため、「現在の」マーカーを参照する必要があります。

この概要を念頭に置いて、この質問とその回答をご覧ください。入力は文字列の形式ですが、それはimplode現在の状況から離れているだけです。

于 2012-06-02T20:13:18.097 に答える