2013-02-15 61 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