1

PHP オブジェクトの 1 次元配列があります。各オブジェクトには 2 つの属性があり、1 つの属性はオブジェクトの一意の ID であり、もう 1 つはその親である配列内の別のオブジェクトの一意の 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
                        )

                )

        )

)
4

2 に答える 2

3

このアルゴリズムを試してください:

// 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);

$idtableID がノードに直接ジャンプするようにルックアップ テーブル ( ) を使用しました。

于 2009-11-10T18:14:57.493 に答える
1

ですから、前兆として、私は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 では、リスト型を使用するか、単に配列をコピーして再度リセットします。

このアルゴリズムが機能するための鍵は、1 回のパスで、子が親の下に配置されることです。これは、順序に関係なく、その 1 回のパスで階層が作成されることを意味します。例に示す親の周りにラッパー配列が必要な場合は、次のようなものをコードの最後に追加するだけです。

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

お役に立てれば。

于 2009-11-10T19:00:26.550 に答える