2012-06-02 127 views
2

我有包含在數組中它是象這樣的數據,從PHP的另一個數組動態構建一個多維數組?

$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']數組可以包含任意數量的元素。每個$file['info']['files']陣列中包含的path陣列是我遇到問題的地方。

它包含有關文件結構的信息。如果只有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 
     } 
    } 
} 

我在添加目錄到數組時遇到了麻煩。我可以手動完成,每次檢查目錄的數組是否存在,如果不存在,創建它,如果它確實存在,然後添加到目錄中,那麼只能下載很多目錄。我用下面的代碼嘗試了這一點,但它只能深入到一個目錄(代碼去了上面說的// 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']; 
} 

我怎麼能動態地創建了存在,並添加所需要銘記的是,目錄結構可能是深層次的任意量的信息,每個目錄陣列?

感謝您花時間閱讀我的相當長的問題,我感謝任何人給我的幫助。

+0

你familar與遞歸? – heximal

+0

@heximal沒有我是新的php – Griff

+0

這種問題(當你不知道有多少層次的嵌套)通過遞歸函數解決。 recusrive是自己調用的功能 – heximal

回答

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 ed作爲函數的返回值。

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 
+0

這真棒!謝謝 :) – Griff

1

爲什麼不用php中的join函數來合併路徑來檢查它是否存在?如果沒有,則逐級檢查文件夾是否存在,如果不存在,則創建並進一步移動。我的觀點是,創建這樣一個動態結構首先是困難而且容易搞砸的。爲什麼不走簡單的路?

1

想象一下,你有一個數組表示目錄結構,它最初是空的,並且將被逐個填充。您需要跟蹤此數組中的「當前」項並遍歷目錄名稱。在每次迭代中,如果當前項目不存在,則在當前項目下創建一個子數組,然後將當前設置爲此子數組。

這可以通過遞歸或迭代完成,由於它是PHP,「當前」標記將需要作爲參考。

有了這個概述,看看this question和那裏的答案。這裏的輸入是以字符串的形式出現的,但這只是一個遠離你目前情況的implode

+0

好的,謝謝我會看看 – Griff

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); 

只要遍歷所有結構,用於合併。

+0

謝謝,我現在就試試看看我能不能工作:) – Griff