2013-02-15 87 views
3

比方說,我有一個這樣的數組:獲得通過數值的所有數組鍵

Array 
(
[Start] => Array 
    (
     [Item 1] => Array 
      (
       [0] => Item 1_1 
       [Item 2_1] => Array 
        (
         [Item 2_1_1] => x 
        ) 

       [1] => Item 3_1 
      ) 

     [0] => Item 2 
     [1] => Item 3 
    ) 

有沒有我可以用它來獲取通向值x路徑中的PHP函數在我的數組,這意味着,在這種情況下,結果將是:

Start, Item 1, Item 2_1, Item 2_1_1, x 
+0

你可以用'連載嘗試()' – fedorqui 2013-02-15 19:57:53

+0

退房圖搜索算法,如BFS和DFS。 – 2013-02-15 19:59:04

+0

array_search()? – 2013-02-15 19:59:13

回答

2

我目前能想到的唯一方法是將大量的嵌套foreach ($array as $key => $value)與一起循環。

儘管如此,使它成爲遞歸的設計會更好,所以使用函數將是明智的。

function recursiveSearch($key, $array) 
{ 
    foreach ($array as $k => $ar) { 
     if (is_array('x', $ar)) { 
      return $k . ', ' . array_search('x', $ar); 
     } else { 
      if ($ar === 'x') { 
       return $k 
      } else { 
       return recursiveSearch($key, $ar); 
      } 
     } 
    } 
} 

只是拿就可以了,不一定是工作或類似的東西。

+0

+1良好的編碼風格和正確的方法 – 2013-02-15 20:08:27

1

您遇到的問題涉及遞歸和/或樹遍歷。 PHP支持使用RecursiveArrayIteratorRecursiveIteratorIterator的數組遍歷樹。

要獲得所有父數組的所有密鑰,您需要從第一級獲取當前深度並獲取密鑰。這由RecursiveIteratorIterator以及getSubIterator()方法支持。這不是在手冊中確實有據可查的,所以這裏是一個例子:

$it = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array) 
); 

foreach ($it as $value) { 
    if ($value !== 'x') continue; 

    $keys = array(); 
    $depth = $it->getDepth(); 
    for ($i = 0; $keys[] = $it->getSubIterator($i)->key(), $depth--; $i++); 

    echo implode(', ', $keys), ', ', $value, "\n"; 
} 

在這個例子中,首先是RecursiveArrayIterator與您創建$array。要啓用樹遍歷,它將被包裝到RecursiveIteratorIterator中。以遞歸方式使用$it -finator和foreach時,這是必需的。

foreach的內部,然後根據您的搜索值檢查數組值。如果不匹配,則繼續下一個值。

但是,如果它確實匹配getDepth()getSubIterator()遞歸迭代器上的方法用於創建鍵數組。

的例子做了以下的輸出:

Start, Item 1, Item 2_1, Item 2_1_1, x 

哪你的描述中的問題相匹配。

因爲這些都是迭代器,你也可以實現它到它自己的類。下面Iterator類不僅允許做樹遍歷在構造函數中所提供的陣列上,而且有一個名爲getKeys()返回包含從最低級別的所有的鍵,在當前深度的陣列方法:

/** 
* Class ArrayRecursiveKeysIterator 
*/ 
class ArrayRecursiveKeysIterator extends RecursiveIteratorIterator 
{ 
    /** 
    * @param array $array 
    */ 
    public function __construct(array $array) 
    { 
     parent::__construct(new RecursiveArrayIterator($array)); 
    } 

    /** 
    * @return array keys 
    */ 
    public function getKeys() 
    { 
     for ($k = [], $i = 0, $m = $this->getDepth(); $i <= $m; $i++) 
      $k[] = $this->getSubIterator($i)->key(); 
     return $k; 
    } 
} 

它更容易使用(也可能用於其他場景)。首先介紹一些基本的使用示例。通過數組顯示每個值的所有鍵。實例的迭代器陣列,並且輸出每每個值的鍵:

$it = new ArrayRecursiveKeysIterator($array); 
foreach ($it as $value) { 
    echo implode(', ', $it->getKeys()), ', ', $value, "\n"; 
} 

這產生了以下的輸出:

Start, Item 1, 0, Item 1_1 
Start, Item 1, Item 2_1, Item 2_1_1, x 
Start, Item 1, 1, Item 3_1 
Start, 0, Item 2 
Start, 1, Item 3 

在您的情況您也需要根據特定值過濾迭代器(這裏是字符串"x"),您可以通過使用RegexIterator這是一個FilterIterator輕鬆完成。這便是您的方案:

$it  = new ArrayRecursiveKeysIterator($array); 
$filter = new RegexIterator($it, '~^x$~'); 
foreach ($filter as $value) { 
    echo implode(', ', $it->getKeys()), ', ', $value, "\n"; 
} 

這裏輸出:

Start, Item 1, Item 2_1, Item 2_1_1, x 

正如你所看到的,它被過濾你感興趣的值

其他相關問題,你「再在可能感興趣的是:

+0

+很好的解釋....爲什麼不只是壓扁數組 – Baba 2013-03-20 11:44:05

+0

Thx。你想扁平什麼?每迭代它已經是線性的順序,只有一個特定的值需要鍵,所以不需要扁平化整個數組我會說。 – hakre 2013-03-20 11:46:28

+0

你是對的..他想要的是遞歸搜索... – Baba 2013-03-20 11:54:26