【问题标题】:Create Multi-Dimensional Array With Algorithm Using Data in Single-Dimensional Array使用一维数组中的数据使用算法创建多维数组
【发布时间】:2009-11-10 17:31:13
【问题描述】:

我有一个 PHP 对象的一维数组。每个对象都有两个属性,一个属性是对象的唯一 ID,另一个是数组中作为其父对象的另一个对象的唯一 ID。例如:

array(3) {
  [0]=>
  object(stdClass)#1 (2) {
    ["ID"]=>
    int(1)
    ["parentID"]=>
    int(0)
  }
  [1]=>
  object(stdClass)#2 (2) {
    ["ID"]=>
    int(3)
    ["parentID"]=>
    int(2)
  }
  [2]=>
  object(stdClass)#3 (2) {
    ["ID"]=>
    int(2)
    ["parentID"]=>
    int(1)
  }
}

我需要把这个一维数组转换成一个多维数组。我已经对此进行了一些尝试,但是如果没有每个嵌套级别的循环,我找不到完成它的方法。该算法需要能够适应假设的无限嵌套级别。我尝试过使用一些递归技术,但从来没有完全正确。

为了增加一点复杂性,我得到的数组中的对象并不总是按合理的顺序排列。我试图在上面的示例中复制它;您会注意到 ID 为 3 的对象在 ID 为 2 的对象之前出现在数组中。因此它们可能也涉及到排序算法。

理想情况下,上面的例子会变成这样:

Array
(
    [0] => Array
        (
            [ID] => 1
            [parentID] => 0
            [0] => Array
                (
                    [ID] => 2
                    [parentID] => 1
                    [0] => Array
                        (
                            [ID] => 3
                            [parentID] => 2
                        )

                )

        )

)

【问题讨论】:

  • 您的样本数据中有父/子递归。节点 3 的父节点是 2,节点 2 的父节点是 3。你打错了吗?
  • 我做到了,谢谢你接听。现在已修复。
  • 这里是否适合使用伪代码答案,或者您是否专门寻找 PhP 响应?

标签: php algorithm arrays multidimensional-array hierarchical-trees


【解决方案1】:

试试这个算法:

// sort objects by parentID
function cmpNodes($a, $b) {
    return $a->parentID - $b->parentID;
}
usort($objects, 'cmpNodes');

// define first node as root of tree
$tree = (array) array_shift($objects);
// lookup table for direct jumps
$idTable = array($tree['ID'] => &$tree);
foreach ($objects as $object) {
    $node = (array) $object;
    // test if parent node exists
    if (!isset($idTable[$node['parentID']])) {
        // Error: parent node does not exist
        break;
    }
    // append new node to the parent node
    $idTable[$node['parentID']][] = $node;
    // set a reference in the lookup table to the new node
    $idTable[$node['ID']] = &$idTable[$node['parentID']][count($idTable[$node['parentID']])-3];
}
// unset($idTable);
var_dump($tree);

我使用查找表 ($idtable) 让 ID 直接跳转到节点。

【讨论】:

    【解决方案2】:

    所以,只是作为一个先驱 - 我不知道 php,真的。我主要是一名 c 风格的语言开发人员(又名 c、Objective c 和 Java)。所以其中一些可能在 php 中更难做到,但这是我会做的尝试:

    //the original input array
    oldArray;
    //the output array
    array[] newArray = new array[];
    
    foreach (element : oldArray) {
        //if the element is at the top, put it at the top of the array
        if (element.parentId == 0) {
            newArray.add(element);
        } else {
            //otherwise, find it's parent and put it in the child array of the parent
            for (potentialParent : oldArray) {
                if (potentialParent.id = element.parentId) {
                    potentialParent.array.add(element);
                    break;
                }
            }
        }
    }
    

    一些注意事项:我假设您使用指针传递所有内容。如果您正在制作对象的副本,那就更难了,但并非不可能。我还假设您可以动态更改数组的大小。同样,我不太了解 php - 如果您不能这样做,那么您将需要一种程序方式来执行此行为。在 Java 中,我会使用列表类型,或者只是复制数组并重新设置它。

    该算法工作的关键是孩子们被放置在他们的父母之下 - 无论他们在哪里 - 一次通过。这意味着,无论顺序如何,都将在该单遍中创建层次结构。如果您需要在示例中显示的父级周围的包装器数组,您可以简单地在代码末尾添加类似这样的内容:

    finalArray = new array[];
    finalArray[0] = newArray;
    

    希望这会有所帮助。

    【讨论】:

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