3

フラットな構造 (この場合は App.net スレッド) から JSON ツリーを作成したいと考えています。

このようなJSONが欲しい

"id": "12345",
"name": "Ringo",
    "data": 
    {
        "avatar": "",
        "text": "We All Live",
    },
    "children": [{
        "id": "34567",
        "name": "John",    
        "data": 
        {
            "avatar": "",
            "text": "In a pink submarine?",
        },
        "children": [{
            "id": "35555",
            "name": "George",    
            "data": 
            {
                "avatar": "",
                "text": "Don't be daft",
            },
            "children": []
        }]
    },{
        "id": "98765",
        "name": "Paul",    
        "data": 
        {
            "avatar": "",
            "text": "In a yellow submarine?",
        },
        "children": []
    }]

したがって、各投稿は複数の子を持つことができます。それぞれの子供は子供を持つことができます。

App.net から返される JSONはスレッド化されていません。

{
    "id": "98765",
    "parent": "12345"
    "details": {
    ...}
},
{
    "id": "34567",
    "parent": "12345"
    "details": {
    ...}
},

json_decode() を使用して、JSON 応答を配列に取得しました。foreach を使用して繰り返すことができます。

各投稿を多次元配列の正しい部分に配置するにはどうすればよいですか?

Parent
|_
  |-child
  |-child
  |  |-child
  |-child

4

3 に答える 3

4

よく忘れられている PHP のハード リンクである参照を使用します。このようなもの:

$postsApp.net API 呼び出しから返された配列があると仮定しています。

(テストされていないため、コンパイル/実行できない可能性があります/エラーが発生する可能性があります/これを行うためのより効率的な方法である可能性があります)

// first throw everything into an associative array for easy access
$references = array();
foreach ($posts as $post) {
    $id = $post['id'];
    $post['children'] = array();
    $references[$id] = $post;
}

// now create the tree
$tree = array();
foreach ($references as &$post) {
    $id = $post['id'];
    $parentId = $post['parent'];
    // if it's a top level object, add it to the tree
    if (!$parentId) {
        $tree[] =& $references[$id];
    }
    // else add it to the parent
    else {
        $references[$parentId]['children'][] =& $post;
    }
    // avoid bad things by clearing the reference
    unset($post);
}

// encode it
print json_encode($tree);
于 2012-08-31T17:46:03.550 に答える
0

あなたが望んでいたことを実現するために、クラスとサンプル スクリプトを作成しました。

フラット構造を階層構造に変換し、孤立した更新 (利用可能な親の更新がないもの) も考慮します。

Update.php

<?php

/**
 * An App.net update.
 */
class Update extends ArrayObject
{
    /**
     * The update's children.
     *
     * @var array
     */
    private $children = array();

    /**
     * The parent update.
     *
     * @var Update
     */
    private $parent;

    /**
     * Adds a child to this update.
     *
     * @param Update The child update.
     */
    public function addChild(self $child)
    {
        $child->setParent($this);

        $this->children[] = $child;
    }

    /**
     * Sets the parent update.
     *
     * @param Update The parent update.
     */
    public function setParent(self $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Converts the update and its children to JSON.
     *
     * @param boolean $encode Automatically encode?
     *
     * @return string The JSON-encoded update.
     */
    public function toJson($encode = true)
    {
        $data = $this->getArrayCopy();

        if ($this->children) {
            $data['children'] = array();

            foreach ($this->children as $child) {
                $data['children'][] = $child->toJSON(false);
            }
        }

        if ($encode) {
            return json_encode($data);
        }

        return $data;
    }
}

build.php

<?php

require 'Update.php';

$updates = <<<UPDATES
[
    {
        "id": "12345",
        "name": "Ringo",
        "data": {
            "avatar": "",
            "text": "We All Live"
        }
    },
    {
        "id": "34567",
        "parent": "12345",
        "name": "John",
        "data": {
            "avatar": "",
            "text": "In a pink submarine?"
        }
    },
    {
        "id": "98765",
        "parent": "12345",
        "name": "Paul",
        "data": {
            "avatar": "",
            "text": "In a yellow submarine?"
        }
    }
]

UPDATES;

$original = json_decode($updates, true);
$parents = array();
$children = array();

foreach ($original as $update) {
    if (empty($update['parent'])) {
        $parents[$update['id']] = $parent = new Update($update); 

        if (isset($children[$update['id']])) {
            foreach ($children[$update['id']] as $child) {
                $parent->addChild($child);
            }

            unset($children[$update['id']]);
        }
    } else {
        $child = new Update($update);

        if (isset($parents[$update['parent']])) {
            $parents[$update['parent']]->addChild($child);
        } else {
            if (false === isset($children[$update['parent']])) {
                $children[$update['parent']] = array();
            }

            $children[$update['parent']][] = $child;
        }
    }
}

// Anything in children at this point are orphans

echo "Parents:\n";

foreach ($parents as $parent) {
    echo $parent->toJson();
}

echo "\n\nOrphans:\n";

foreach ($children as $parent => $orphans) {
    foreach ($orphans as $orphan) {
        echo $orphan->toJson();
    }
}
于 2012-08-31T18:15:04.763 に答える
0

ここで答えをスケッチするだけです.RAMにすべてのエントリを保持できると仮定すると、それ以外の場合は、いくつかの順序付けの仮定を行い、完全なユニットが完了したときに配列をクリアする必要があります.

posts詳細と子の配列を含む構造を保持する id によってインデックス付けされた配列を作成します。次に、入力配列と各要素を反復処理します。

  • posts[id]まだ作成されていない場合は作成する
  • の詳細を記入してくださいpost[id]
  • 親がある場合は、ルックアップし (必要に応じて作成します。順序がどのようになっているかわかりません) posts[parent_id]、この構造をそこの子に追加します。

最後に、すべての投稿を反復処理できます。親のない投稿は、子が適切に入力されたルートです。

于 2012-08-31T17:26:41.890 に答える