Mam duży problem (najwyraźniej tak prosty do rozwiązania), że próbowałem przez ponad 24 godziny, aby utworzyć funkcję, aby obrócić tablicę na wielowymiarowe z głębokości .

Moja tablica jest

$array = array(
    array("name" => "Root_1", "depth"=> "1"),
    array("name" => "Children","depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Children","depth"=> "3"),
    array("name" => "Root_2", "depth"=> "1"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2"),
    array("name" => "Children", "depth"=> "2")
)

Chcę, żeby wynik był:

$array = array(
  array("name" => "Root_1", "depth"=> "1", "children" => array(
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array(
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array())
            )
        )), 
  array("name" => "Root_2", "depth"=> "1", "children" => array(
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array()),
        array("name" => "Children", "depth"=> "2", "children" => array(
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array()),
                array("name" => "Children", "depth"=> "3", "children" => array())
            )
        )), 
);

Co próbowałem:

<?php


function createArray($array, $depth) {
$result = array();
$item = array();


if(isset($array["depth"])) {
    if(intval($array["depth"]) >= $depth) {
        array_push($result, $array);
    }
} else {
    foreach($array as $value) {
        $depthToInt = intval($value["depth"]);
        if($depthToInt === $depth) {
            array_push($result, $value);
            $item = $value;
        } else {
            $item["children"] = createArray($value, $item["depth"]);
        }
    }
}
return $result; 

}

5
Vegetus 22 luty 2019, 17:33

2 odpowiedzi

Najlepsza odpowiedź

OK, wyraźnie, że chcemy rekurencyjne rozwiązanie.

Dla każdego elementu (począwszy od wirtualnego korzenia) chcemy odzyskać dzieci. Powiedzmy, że dostajemy dzieci, filtrując wszystko, co jest nie dzieci.

Jakie są nasze kryteria filtra?

  1. Dziecko ma głębokość większą niż rodzic.
  2. Dziecko ma indeks większy niż rodzic.
  3. Dziecko należy do bloku przedmiotów o tej samej głębokości. Losujmy to, ponieważ dziecko ma mniejsze niż początek następnego bloku. Nazwijmy ten indeks mniejszy niż limit.

Potrzebujemy więc:

  1. Funkcja, która dostaje dzieciom dla danego indeksu, głębokości i limitu.
  2. Funkcja pomocnika, która otrzymuje limit dla danego indeksu.

Oto, z czym skończyłem. Nie sądzę, że to jest idealne (niejasne wątpię do mojej logiki limitowej), ale jest to głównie dla twoich przykładowych danych.

$array = array(
    array( 'name' => 'Root_1', 'depth' => '1' ),
    array( 'name' => 'Children 1-1', 'depth' => '2' ),
    array( 'name' => 'Children 1-2', 'depth' => '2' ),
    array( 'name' => 'Children 1-2-1', 'depth' => '3' ),
    array( 'name' => 'Children 1-3', 'depth' => '2' ),
    array( 'name' => 'Children 1-3-1', 'depth' => '3' ),
    array( 'name' => 'Children 1-3-2', 'depth' => '3' ),
    array( 'name' => 'Children 1-3-3', 'depth' => '3' ),
    array( 'name' => 'Root_2', 'depth' => '1' ),
    array( 'name' => 'Children 2-1', 'depth' => '2' ),
    array( 'name' => 'Children 2-2', 'depth' => '2' ),
    array( 'name' => 'Children 2-3', 'depth' => '2' ),
    array( 'name' => 'Children 2-3-1', 'depth' => '3' ),
    array( 'name' => 'Children 2-3-2', 'depth' => '3' ),
    array( 'name' => 'Children 2-3-3', 'depth' => '3' ),
);

function getChildren( $array, $index = - 1 ) {

    $depth = isset( $array[ $index ]['depth'] ) ? (int) $array[ $index ]['depth'] : 0;
    $limit = $index === - 1 ? count( $array ) - 1 : findLimit( $array, $index );

    $result = array_filter( $array, function ( $item, $key ) use ( $index, $depth, $limit ) {

        $isDeeper      = (int) $item['depth'] === $depth + 1;
        $isAfter       = $key > $index;
        $isBeforeLimit = $key <= $limit;

        return $isDeeper && $isAfter && $isBeforeLimit;
    }, ARRAY_FILTER_USE_BOTH );

    foreach ( $result as $key => $item ) {
        $result[ $key ]['children'] = getChildren( $array, $key );
    }

    return $result;
}

function findLimit( $array, $index ) {
    $depth   = (int) $array[ $index ]['depth'];
    $limit   = $index;
    $current = $limit + 1;

    while ( isset( $array[ $current ] ) && ( (int) $array[ $current ]['depth'] > $depth ) ) {
        $current ++;
        $limit ++;
    }

    return $limit;
}

$result = getChildren( $array );

var_dump( $result );

Wynik:

array(2) {
  [0]=>
  array(3) {
    ["name"]=>
    string(6) "Root_1"
    ["depth"]=>
    string(1) "1"
    ["children"]=>
    array(3) {
      [1]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-1"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [2]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-2"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(1) {
          [3]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-2-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
      [4]=>
      array(3) {
        ["name"]=>
        string(12) "Children 1-3"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(3) {
          [5]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [6]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-2"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [7]=>
          array(3) {
            ["name"]=>
            string(14) "Children 1-3-3"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
    }
  }
  [8]=>
  array(3) {
    ["name"]=>
    string(6) "Root_2"
    ["depth"]=>
    string(1) "1"
    ["children"]=>
    array(3) {
      [9]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-1"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [10]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-2"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(0) {
        }
      }
      [11]=>
      array(3) {
        ["name"]=>
        string(12) "Children 2-3"
        ["depth"]=>
        string(1) "2"
        ["children"]=>
        array(3) {
          [12]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-1"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [13]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-2"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
          [14]=>
          array(3) {
            ["name"]=>
            string(14) "Children 2-3-3"
            ["depth"]=>
            string(1) "3"
            ["children"]=>
            array(0) {
            }
          }
        }
      }
    }
  }
}

2
Rarst 22 luty 2019, 19:24

Jestem trochę za późno, ale jeśli jesteś zainteresowany rozwiązaniem nie rekurencyjnym, tutaj jest prosty pętla tylko ( (n) ):

<?php

function treeify(array $input): array
{
    $result = [];
    $path = [];

    foreach ($input as &$entry) {
        $entry['children'] = [];

        $depth = $entry['depth'] - 1;
        $path = \array_slice($path, 0, $depth);
        $path[] = &$entry;

        0 === $depth
            ? $result[] = &$entry
            : $path[$depth - 1]['children'][] = &$entry;
    }

    return $result;
}

print_r(treeify([
    ['name' => 'Root_1', 'depth' => 1],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
            ['name' => 'Children', 'depth' => 3],
            ['name' => 'Children', 'depth' => 3],
            ['name' => 'Children', 'depth' => 3],
                ['name' => 'Children', 'depth' => 4],
        ['name' => 'Children', 'depth' => 2],
    ['name' => 'Root_2', 'depth'=> 1],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
        ['name' => 'Children', 'depth' => 2],
            ['name' => 'Children', 'depth' => 3],
    ['name' => 'Root_3', 'depth' => 1],
    ['name' => 'Root_4', 'depth' => 1],
        ['name' => 'Children', 'depth' => 2],
]));

Demo: https://3v4l.org/1ykvy

3
Yoshi 26 luty 2019, 08:22