Как отсортировать плоский массив в многомерное дерево - PullRequest
4 голосов
/ 24 октября 2011

У меня есть таблица, как

id    catagory      suboff

1     software       0
2     programming    1
3     Testing        1
4     Designing      1
5     Hospital       0
6     Doctor         5
7     Nurses         5
9     Teaching       0
10    php programming 2
11    .net programming 2

Как написать код для получения всей этой информации в многомерном массиве на основе suboff следующим образом:

-software
--programming
---php programming
--- .net programming
--testing
--designing
-hospital 
--doctor
--nurses
-teaching

Ответы [ 10 ]

3 голосов
/ 24 октября 2011

Предполагая MySQL в качестве движка БД:

// We'll need two arrays for this
$temp = $result = array();

// Get the data from the DB
$table = mysql_query("SELECT * FROM table");

// Put it into one dimensional array with the row id as the index
while ($row = mysql_fetch_assoc($table)) {
  $temp[$row['id']] = $row;
}

// Loop the 1D array and create the multi-dimensional array
for ($i = 1; isset($temp[$i]); $i++) {
  if ($temp[$i]['suboff'] > 0) {
    // This row has a parent
    if (isset($temp[$temp[$i]['suboff']])) {
      // The parent row exists, add this row to the 'children' key of the parent
      $temp[$temp[$i]['suboff']]['children'][] =& $temp[$i];
    } else {
      // The parent row doesn't exist - handle that case here
      // For the purposes of this example, we'll treat it as a root node
      $result[] =& $temp[$i];
    }
  } else {
    // This row is a root node
    $result[] =& $temp[$i];
  }
}

// unset the 1D array
unset($temp);

// Here is the result
print_r($result);

Используйте ссылки для такой работы.

2 голосов
/ 24 октября 2011

Демо: http://ideone.com/vk4po

$array = array(
array('1','software','0'),
array('2','programming','1'),
array('3','Testing','1'),
array('4','Designing','1'),
array('5','Hospital','0'),
array('6','Doctor','5'),
array('7','Nurses','5'),
array('9','Teaching','0'),
array('10','php programming','2'),
array('11','.net programming','2')
);

function menu_sort($results, $master = 0)
{

    $open = array();
    $return = NULL;

    foreach($results as $result)
    {
        if($result[2] == $master){

            if(!$open){
                $return .= '<ul>';
                $open = true;
            }

            $return .= '<li>'.$result[1];

            $return .= menu_sort($results, $result[0]);
            $return .= '</li>';

        }
    }

    if($open)
        $return .= '</ul>';

    return $return;

}

echo menu_sort($array);

Результат ...

software
    programming
        php programming
        .net programming
    Testing
    Designing
Hospital
    Doctor
    Nurses
Teaching
1 голос
/ 12 января 2017

Это то, что я только что написал для своего приложения, и оно работает как шарм:)

$array = [
    'i' => ['key' => 'i', 'name' => 'php programming', 'parent' => 'b'], 
    'g' => ['key' => 'g', 'name' => 'Nurses', 'parent' => 'e'],
    'j' => ['key' => 'j', 'name' => '.net programming', 'parent' => 'b'], 
    'b' => ['key' => 'b', 'name' => 'programming', 'parent' => 'a'],
    'a' => ['key' => 'a', 'name' => 'software', 'parent' => 'asd'],
    'c' => ['key' => 'c', 'name' => 'Testing', 'parent' => 'a'], 
    'd' => ['key' => 'd', 'name' => 'Designing', 'parent' => 'a'], 
    'e' => ['key' => 'e', 'name' => 'Hospital', 'parent' => 'asd'],  
    'f' => ['key' => 'f', 'name' => 'Doctor', 'parent' => 'e'], 
    'h' => ['key' => 'h', 'name' => 'Teaching'],  
];

function getAsTree(array &$array)
{
    foreach ($array as $key => $item) {
        if (isset($item['parent']) && isset($array[$item['parent']])) {
            $array[$item['parent']]['children'][] = $item;
            unset($array[$key]);
            return getAsTree($array);
        }
    }

    return $array;
}

И вот результат:

--- a: software
------ b: programming
--------- i: php programming
--------- j: .net programming
------ c: Testing
------ d: Designing
--- e: Hospital
------ g: Nurses
------ f: Doctor
--- h: Teaching
1 голос
/ 15 декабря 2011

Этот класс преобразует массив плоских категорий в массив структурированных деревьев:

<code><?php

/**
 * Creates a structured tree out of a flat category list
 */
class CategoryTree {

  /**
   *
   * @var array
   */
  protected $categories = array();

  /**
   *
   * @var array
   */
  protected $tree = array();

  /**
   * Default constructor
   * @param array $categories 
   */
  function __construct(array $categories) {
    $this->categories = $categories;
  }

  /**
   * Process a subtree
   * @param array $categories
   * @param integer $parentId
   * @return array 
   */
  protected function getSubtree(array $categories, $parentId = 0) {
    $tree = array();

    foreach($categories as $category) {
      if($category['suboff'] == $parentId) {
        $tree[$category['id']] = $category;
        $tree[$category['id']]['children'] = $this->getSubtree($categories, $category['id']);
      }
    }

    return $tree;
  }

  /**
   * Get the category tree as structured array
   * @return array 
   */
  public function getTree() {
    if(empty($this->tree)) {
      $this->tree = $this->getSubtree($this->categories, 0);
    }
    return $this->tree;
  }

  /**
   * Get the category tree as string representation
   * @return string
   */
  public function __toString() {
    return "<pre>" . print_r($this->getTree(), true) . "
"; } } // Теперь используем класс с данными givven: $ Categories = массив ( массив ( 'id' => 1, 'category' => 'software', 'suboff' => 0 ), массив ( 'id' => 2, «категория» => «программирование», 'suboff' => 1 ), массив ( 'id' => 3, 'category' => 'Тестирование', 'suboff' => 1 ), массив ( 'id' => 4, 'category' => 'Проектирование', 'suboff' => 1 ), массив ( 'id' => 5, 'category' => 'Больница', 'suboff' => 0 ), массив ( 'id' => 6, 'category' => 'Доктор', 'suboff' => 5 ), массив ( 'id' => 7, 'category' => 'Медсестры', 'suboff' => 5 ), массив ( 'id' => 9, 'category' => 'Teaching', 'suboff' => 0 ), массив ( 'id' => 10, 'category' => 'PHP программирование', 'suboff' => 2 ), массив ( 'id' => 11, 'category' => '.net Программирование', 'suboff' => 2 ) ); $ myTree = new CategoryTree ($ category); echo $ myTree; ?>
1 голос
/ 24 октября 2011

Как бы я это сделал:

  1. Сначала вам нужно разобрать эту таблицу.Я полагаю, вы можете сделать это самостоятельно;если нет, Google "регулярные выражения", они ваши друзья.

  2. Структура данных, с которой вы работаете, - это классическое дерево .Вам понадобятся два массива для работы с ним.Сначала это массив узлов, $nodes, где ключи - это идентификаторы узлов, а значения - имена узлов, и $links, где каждый ключ - это родительский узел, а каждое значение - это массив дочерних элементов ($links[$id][] = $suboff для каждогоэлемента будет достаточно).

  3. Теперь вам нужно рекурсивно спускаться к дереву, которое у вас есть.Вы вводите функцию с такой сигнатурой:

    function print_node( $nodeID, $level = 1 )
    

    Эта функция должна печатать сам узел (информация хранится в $ узлов) с черточками заполнения $ level и вызывать себя для отображения всех дочерних узлов.Они, в свою очередь, отобразят все свои подузлы и т. Д. Вам просто нужно вызвать эту функцию для узлов верхнего уровня.

0 голосов
/ 23 августа 2016

Это решение отлично работает для меня.

$array = array(
    array('1','software','0'),
    array('2','programming','1'),
    array('3','Testing','1'),
    array('4','Designing','1'),
    array('5','Hospital','0'),
    array('6','Doctor','5'),
    array('7','Nurses','5'),
    array('9','Teaching','0'),
    array('10','php programming','2'),
    array('11','.net programming','2')
);

$newArray = getTree($array);

function getTree( $rows, $suboff = 0) {

    $return = array();

    foreach($rows as $row) {

        if($row[2] == $suboff){

            $newrow = $row;

            $subs = $this->getTree($rows, $row[0]);

            if ( !empty($subs) ) {
                $newrow['subs'] = $subs;
            }

            $return[] = $newrow;

        }
    }

    return $return;

}
0 голосов
/ 24 октября 2011

Вот другой подход, который должен быть очень простым для понимания.Для этого требуется, чтобы таблица была упорядочена по suboff, т.е.

SELECT * FROM table ORDER BY suboff

. Предполагая, что результат сохранен в $table, вы можете использовать этот очень краткий код php:

// this will hold the result
$tree = array();
// used to find an entry using its id
$lookup = array();
foreach($table as $row){
  if($row['suboff'] === 0){
    // this has no parent, add it at base level
    $tree[$row['category']] = array();
    // store a reference
    $lookup[$row['id']] =& $tree[$row['category']];
  }else{
    // find the right parent, add the category
    $lookup[$row['suboff']][$row['category']] = array();
    // store a reference
    $lookup[$row['id']] =& $lookup[$row['suboff']][$row['category']];
  }
}
0 голосов
/ 24 октября 2011

В PHP я получаю данные из базы данных:

"SELECT* FROM Table WHERE suboff LIKE 0"
foreach(item..)
   "SELECT* FROM Table WHERE suboff LIKE item.ID"
       foreach(item2..)
          $result[item][item2]
0 голосов
/ 24 октября 2011

Вы захотите прочитать всю таблицу в память и превратить ее в дерево, где каждый узел может быть идентифицирован с соответствующим номером идентификатора.Затем выполните предварительный заказ дерева, чтобы распечатать его.

0 голосов
/ 24 октября 2011

ИМХО логика такова:

  1. Получить все элементы корня (программное обеспечение, больница и т. Д.)
  2. Foreach root берет субэлемент (ы) (для программного обеспечения, которое вы 'займемся программированием, тестированием и проектированием)
  3. Добавьте подэлемент (ы) в качестве подмассива
  4. Рекурсивно зацикливайтесь на подмассиве, который вы только что добавили
...