按“父/子”关系排序多维数组

问题描述 投票:0回答:1
I have an array that looks like this:


[0] => Array
    (
        [id] => 111
        [parent_id] => 222
        [field_1] => Main document
    )
[1] => Array
    (
        [id] => 123
        [parent_id] => 222
        [field_1] => Main document
    )
[2] => Array
    (
        [id] => 777
        [parent_id] => 111
        [field_1] => Child document
    )
[3] => Array
    (
        [id] => 345
        [parent_id] => 222
        [field_1] => Main document
    )
[4] => Array
    (
        [id] => 789
        [parent_id] => 123
        [field_1] => Child document
    )
[5] => Array
    (
        [id] => 567
        [parent_id] => 345
        [field_1] => Child document
    )

您可能会注意到,在字段1中有主文档和子文档。子文档的[parent_id]等于主文档的[id]。我该如何按ID和父ID对它们进行排序,以便在每个主文档之后都应该是子文档?我知道我应该遍历它,但是有些东西我无法保留,并且没有按照我想要的方式进行排序。

这应该是这样:

  [0] => Array
    (
    [id] => 111
    [parent_id] => 222
    [field_1] => Main document
    )

  [1] => Array
    (
    [id] => 777
    [parent_id] => 111
    [field_1] => Child document
    )

  [2] => Array
    (
    [id] => 123
    [parent_id] => 222
    [field_1] => Main document
    )

  [3] => Array
    (
    [id] => 789
    [parent_id] => 123
    [field_1] => Child document
    )

  [4] => Array
    (
    [id] => 345
    [parent_id] => 222
    [field_1] => Main document
    )

  [5] => Array
    (
    [id] => 567
    [parent_id] => 345
    [field_1] => Child document
    )
php arrays sorting multidimensional-array associative
1个回答
0
投票

基本上,您需要做的是将初始数组分为两部分:主文档数组和子文档数组。然后,只需遍历这些数组并组成一个新数组,在该数组中主文档后跟一系列子元素。

请注意,这是用php7.4编写的,我可能使用了以前版本php中没有的某些语法。

// extract main documents and sort them by id
$main_documents = array_filter($input, fn ($document) => $document['field_1'] === 'Main document');
usort($main_documents, function ($a, $b) {
    return ($a['id'] <=> $b['id']);
});

// extract child documents and sort them by parent id
$child_documents = array_filter($input, fn ($document) => $document['field_1'] === 'Child document');
usort($child_documents, function ($a, $b) {
    return ($a['parent_id'] <=> $b['parent_id']);
});

$output = [];

// go through each main document and insert it into the output array
foreach ($main_documents as $main_index => $main_document) {
    $output[] = $main_document;
    // go through all children and see whether they are a child of current main document
    foreach ($child_documents as $child_index => $child_document) {
        // if they are then insert this child after the main element
        if ($main_document['id'] === $child_document['parent_id']) {
            $output[] = $child_document;
            // delete inserted child element from the children array so that next iteration can be faster
            unset($child_documents[$child_index]);
        }
    }
    // delete current main element from the array so that next iteration can be faster
    unset($main_documents[$main_index]);
}

还有一个用于初始输入数组的较短版本:

$output = [];
foreach ($input as $main_index => $document) {
    if ($document['field_1'] === 'Main document') {
        $output[] = $document;
        unset($input[$main_index]);
        foreach ($input as $subloop_index => $subloop_document) {
            if ($document['id'] === $subloop_document['parent_id']) {
                $output[] = $subloop_document;
                unset($input[$subloop_index]);
            }
        }
    }
}

尽管我的回答不是很有效-嵌套循环永远不是一个好习惯,但是如果性能不是代码中的问题或效果可忽略,那么我认为应该这样做。

© www.soinside.com 2019 - 2024. All rights reserved.