根据父 ID 值将数组从一维转换为多维

发布于 2024-12-09 14:08:11 字数 869 浏览 1 评论 0原文

我有一个代表多维数据的一维对象数组:

array(
    array(
        "id" => 45,
        "parent_id" => null
    ),
    array(
        "id" => 200,
        "parent_id" => 45
    ),
    array(
        "id" => 345,
        "parent_id" => 45
    ),
    array(
        "id" => "355",
        "parent_id" => 200
    )
);

我应该如何将其转换为多维数组:

array(
    array(
        "id" => 45,
        "parent_id" => null,
        "children" => array(
            array(
                "id" => 200,
                "parent_id" => 45,
                "children" => array(
                    "id" => "355",
                    "parent_id" => 200
                )

            ),
            array(
                "id" => 345,
                "parent_id" => 45
            ),
        )
    ),
);

I've got a one-dimensional array of objects that represent multi-dimensional data:

array(
    array(
        "id" => 45,
        "parent_id" => null
    ),
    array(
        "id" => 200,
        "parent_id" => 45
    ),
    array(
        "id" => 345,
        "parent_id" => 45
    ),
    array(
        "id" => "355",
        "parent_id" => 200
    )
);

How should I convert it into a multi-dimensional array:

array(
    array(
        "id" => 45,
        "parent_id" => null,
        "children" => array(
            array(
                "id" => 200,
                "parent_id" => 45,
                "children" => array(
                    "id" => "355",
                    "parent_id" => 200
                )

            ),
            array(
                "id" => 345,
                "parent_id" => 45
            ),
        )
    ),
);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青朷 2024-12-16 14:08:11

以下代码示例将数组 $array 转换为您要查找的树结构:

// key the array by id
$keyed = array();
foreach($array as &$value)
{
    $keyed[$value['id']] = &$value;
}
unset($value);
$array = $keyed;
unset($keyed);

// tree it
$tree = array();
foreach($array as &$value)
{
    if ($parent = $value['parent_id'])
        $array[$parent]['children'][] = &$value;
    else
        $tree[] = &$value;
}
unset($value);
$array = $tree;
unset($tree);

var_dump($array); # your result

如果存在现有的,则此操作不起作用em> 父 ID 为 0。但可以很容易地改变以反映这一点。

这是一个相关的问题,原始数组已经被键入,因此解决方案的前半部分可以省去: 嵌套数组。第三层正在消失

编辑:

那么这是如何工作的呢?这是利用 PHP 变量别名(也称为 引用)用于存储 a) 节点别名 ($keyed) 和 b) 用于构建新树顺序 ($tree) 的(临时)数组。

你能[...]解释一下$array = $keyed$array = $tree和未设置的目的吗?

由于 $keyed$tree 都包含对 $array 中值的引用,我首先将该信息复制到 $array< /code>,例如:

$array = $keyed;

现在 $keyed 仍然设置(并且包含对与 $array 中相同值的引用),$keyed未设置:

unset($keyed);

这会取消设置 $keyed 中的所有引用并确保 $array 中的所有值不再被引用(该值的引用计数减一)。

如果迭代后未取消设置临时数组,则它们的引用仍然存在。如果您在 $array 上使用 var_dump,您会看到所有值前面都会有一个 &,因为它们仍然被引用。 unset($keyed) 删除这些引用,再次 var_dump($array),您将看到 & 消失了。

我希望这是可以理解的,如果您不熟悉参考文献,有时会很难理解它们。它经常帮助我将它们视为变量别名。

如果您想要锻炼身体,请考虑以下事项:

如何通过一次 foreach 迭代将 $array 从平面转换为树?

请自行决定何时点击包含解决方案的链接。

The following code-example converts the array $array into the tree-structure you're looking for:

// key the array by id
$keyed = array();
foreach($array as &$value)
{
    $keyed[$value['id']] = &$value;
}
unset($value);
$array = $keyed;
unset($keyed);

// tree it
$tree = array();
foreach($array as &$value)
{
    if ($parent = $value['parent_id'])
        $array[$parent]['children'][] = &$value;
    else
        $tree[] = &$value;
}
unset($value);
$array = $tree;
unset($tree);

var_dump($array); # your result

This does not work, if there is an existing parent id that is 0. But could be easily changed to reflect that.

This is a related question, that has the original array already keyed, so the first half of the solution could be spared: Nested array. Third level is disappearing.

Edit:

So how does this work? This is making use of PHP variable aliasing (also known as references) and (temporary) arrays that are used to store a) aliases to the nodes ($keyed) and b) to build the new tree order ($tree).

Could you [...] explain the purpose of $array = $keyed, $array = $tree and the unsets?

As both, $keyed and $tree contain references to values in $array, I first copy over that information into $array, e.g.:

$array = $keyed;

As now $keyed is still set (and contains references to the same values as in $array), $keyed is unset:

unset($keyed);

This un-sets all references in $keyed and ensures, that all values in $array aren't referenced any longer (the value's refcount is reduced by one).

If the temporary arrays are not unset after the iteration, their references would still exist. If you use var_dump on $array, you would see that all values would have a & in front, because they are still referenced. unset($keyed) removes these references, var_dump($array) again, and you will see the &s are gone.

I hope this was understandable, references can be hard to follow sometimes if you're not fluent with them. It often helps me to think about them as variable aliases.

If you want some exercise, consider the following:

How to convert your $array from flat to tree with one foreach iteration?

Decide on your own when you would like to click the link which contains a Solution.

相守太难 2024-12-16 14:08:11
function convertArray ($array) {
  // First, convert the array so that the keys match the ids
  $reKeyed = array();
  foreach ($array as $item) {
    $reKeyed[(int) $item['id']] = $item;
  }
  // Next, use references to associate children with parents
  foreach ($reKeyed as $id => $item) {
    if (isset($item['parent_id'], $reKeyed[(int) $item['parent_id']])) {
      $reKeyed[(int) $item['parent_id']]['children'][] =& $reKeyed[$id];
    }
  }
  // Finally, go through and remove children from the outer level
  foreach ($reKeyed as $id => $item) {
    if (isset($item['parent_id'])) {
      unset($reKeyed[$id]);
    }
  }
  return $reKeyed;
}

我确信这可以减少到只有两个循环(结合第二个和第三个),但现在我无法弄清楚如何...

注意这个函数依赖于parent_id 对于没有父项为 NULL 或根本未设置的项,因此 isset() 在最后一个循环。

function convertArray ($array) {
  // First, convert the array so that the keys match the ids
  $reKeyed = array();
  foreach ($array as $item) {
    $reKeyed[(int) $item['id']] = $item;
  }
  // Next, use references to associate children with parents
  foreach ($reKeyed as $id => $item) {
    if (isset($item['parent_id'], $reKeyed[(int) $item['parent_id']])) {
      $reKeyed[(int) $item['parent_id']]['children'][] =& $reKeyed[$id];
    }
  }
  // Finally, go through and remove children from the outer level
  foreach ($reKeyed as $id => $item) {
    if (isset($item['parent_id'])) {
      unset($reKeyed[$id]);
    }
  }
  return $reKeyed;
}

I feel sure this can be reduced to only two loops (combining the second and third) but right now I can't for the life of me figure out how...

NOTE This function relies on parent_id for items with no parent being either NULL or not set at all, so that isset() returns FALSE in the last loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文