【问题标题】:get path from child node to parent php array获取从子节点到父php数组的路径
【发布时间】:2013-09-12 19:17:06
【问题描述】:

我有一个像下面这样的数组,数组的大小和元素不是固定的,它完全是动态生成的

array(
    'marketplace'   => array(
        'browse request' => array('request type 1', 'request type 2'),
        'browse lab',
    ),
    'marketplace2'  => array('browse request2', 'browse lab2'),
    'submitrequest' => array(''),
    'aboutus'       => array('')
)

我想获取从给定子节点到根节点的路径

假设'request type 2',那么路径将是'marketplace -> browse request -> request type 2'

再加一个'submitrequest',那么路径就是'submitrequest'

任何帮助将不胜感激。谢谢

【问题讨论】:

  • "来自给定的子节点" => 它究竟是如何“给定”的?输入是否存在数组中somewhere的某个值,以便解决方案包括找到它?请注意,您的“提交请求”示例不同意此描述。另外,如果该值存在不止一次怎么办?
  • 您的输入是字符串吗?
  • 是的,我的输入名称只是一个字符串,将是数组的元素/键名称
  • @Bajrang: "request type 2" 不是这个数组中的键。
  • 数据构造(数组)不擅长这种事情,Tree 擅长,你应该先建一棵树。然后你的问题就变成了路径搜索问题。

标签: php arrays


【解决方案1】:

如果您的输入是唯一的字符串,因此可以清楚地识别,您只需将值(以及您添加的键)与字符串进行比较,如果找到,则获取路径:

$string = 'request type 2';

$path = NULL;

$it = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST
);
foreach ($it as $key => $value) {
    if ($key !== $string and $value !== $string) {
        continue;
    }

    $path = [$string];
    for ($count = $it->getDepth(); $count && $count--;) {
        array_unshift($path, $it->getSubIterator($count)->key());
    }
    $path = implode(' -> ', $path);
    break;
}

var_dump($path); # string(47) "marketplace -> browse request -> request type 2"

类似/相关问答:


较早的回答:您可能在这里遗漏了一些要点。首先,您需要清楚地标识要查找路径的元素/节点(对象)。

你没有在你的问题中概述你是如何做到这一点的,你只给出了数组,然后给出了字符串。

如果你的意思是引用节点并且你想获得它的路径,我会在这个答案中举例说明它是如何工作的。

首先,让我们引用对象(一般意义上的)来获取路径:

// specify the node to search for
$node = &$array['marketplace']['browse request'][1];

由于 PHP 不允许识别字符串 - 并且您的数组可能多次包含相同的字符串 - 此节点需要转换为可识别的对象。为了保留原始字符串值,将其存储到另一个变量中:

// make the node identifiable (so that it can be searched independent to it's string value, e.g. duplicates)
$string = "$node";
$node   = new stdClass();

现在您的原始数组具有要搜索的节点以获取可识别的路径。 print_r 现在看起来如下(缩短):

Array
(
    [marketplace] => Array
        (
            [browse request] => Array
                (
                    [0] => request type 1
                    [1] => stdClass Object
                    ...

这是必要的,因为如果我们搜索数组并找到 那个 对象,并且我们会跟踪到目前为止在搜索中使用的路径,我们在找到该对象时获得了路径。

这正是我们现在在迭代器的帮助下所做的。 PHP 已经知道如何遍历数组,在我们自己的一点帮助下,这甚至适用于包含对象的数组:

class MyRecursiveIterator extends RecursiveArrayIterator
{
    public function hasChildren() {
        return is_array($this->current());
    }
}

将此RecursiveIterator 与PHP 的标准树遍历RecursiveIteratorIterator 一起使用,我们可以在找到该对象时生成路径:

$path = NULL;

$it   = new RecursiveIteratorIterator(new MyRecursiveIterator($array));
foreach ($it as $value) {
    if ($value !== $node) {
        continue;
    }

    $path = [$string];
    for ($count = $it->getDepth(); $count && $count--;) {
        array_unshift($path, $it->getSubIterator($count)->key());
    }
    $path = implode(' -> ', $path);
    break;
}

var_dump($path); # string(47) "marketplace -> browse request -> request type 2"

完整示例代码一目了然 (Demo):

<?php
/**
 * get path from child node to parent php array
 * @link https://stackoverflow.com/a/18696550/367456
 */

class MyRecursiveIterator extends RecursiveArrayIterator
{
    public function hasChildren()
    {
        return is_array($this->current());
    }
}


$array = array(
    'marketplace'   => array(
        'browse request' => array('request type 1', 'request type 2'),
        'browse lab',
    ),
    'marketplace2'  => array('browse request2', 'browse lab2'),
    'submitrequest' => array(''),
    'aboutus'       => array('')
);

// specify the node to search for
$node = & $array['marketplace']['browse request'][1];

// make the node identifiable (so that it can be searched independent to it's string value, e.g. duplicates)
$string = "$node";
$node   = new stdClass();

$path = NULL;

$it   = new RecursiveIteratorIterator(new MyRecursiveIterator($array));
foreach ($it as $value) {
    if ($value !== $node) {
        continue;
    }

    $path = [$string];
    for ($count = $it->getDepth(); $count && $count--;) {
        array_unshift($path, $it->getSubIterator($count)->key());
    }
    $path = implode(' -> ', $path);
    break;
}

var_dump($path); # string(47) "marketplace -> browse request -> request type 2"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多