PHP: сортировка массива - PullRequest
4 голосов
/ 17 мая 2009

У меня есть массив с данными из таблицы MySQL в модели вложенного множества, который я хочу отсортировать не только по алфавиту, но и с дочерними узлами непосредственно после родительского узла. Пример - массив для сортировки (до сортировки):

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Kompetenser
            [parent] => 0
            [depth] => 0
        )

    [1] => Array
        (
            [id] => 2
            [name] => Administration
            [parent] => 1
            [depth] => 1
        )

    [2] => Array
        (
            [id] => 11
            [name] => Organisation
            [parent] => 2
            [depth] => 2
        )

    [3] => Array
        (
            [id] => 4
            [name] => Arbetsledning
            [parent] => 2
            [depth] => 2
        )

    [4] => Array
        (
            [id] => 17
            [name] => Planering
            [parent] => 2
            [depth] => 2
        )

    [5] => Array
        (
            [id] => 9
            [name] => Hantverke
            [parent] => 1
            [depth] => 1
        )

    [6] => Array
        (
            [id] => 10
            [name] => Snickeri
            [parent] => 9
            [depth] => 2
        )

    [7] => Array
        (
            [id] => 12
            [name] => Språk
            [parent] => 1
            [depth] => 1
        )

    [8] => Array
        (
            [id] => 13
            [name] => Tolk
            [parent] => 12
            [depth] => 2
        )

    [9] => Array
        (
            [id] => 15
            [name] => Arabiska
            [parent] => 13
            [depth] => 3
        )

    [10] => Array
        (
            [id] => 14
            [name] => Persiska
            [parent] => 13
            [depth] => 3
        )

    [11] => Array
        (
            [id] => 16
            [name] => Polska
            [parent] => 13
            [depth] => 3
        )

    [12] => Array
        (
            [id] => 18
            [name] => Apotekare
            [parent] => 1
            [depth] => 1
        )

    [13] => Array
        (
            [id] => 19
            [name] => Dotkorand
            [parent] => 1
            [depth] => 1
        )

    [14] => Array
        (
            [id] => 21
            [name] => Atomfysik
            [parent] => 19
            [depth] => 2
        )

    [15] => Array
        (
            [id] => 20
            [name] => Fysik
            [parent] => 19
            [depth] => 2
        )

    [16] => Array
        (
            [id] => 22
            [name] => Ekonom
            [parent] => 1
            [depth] => 1
        )

    [17] => Array
        (
            [id] => 23
            [name] => Industriell ekonomi
            [parent] => 22
            [depth] => 2
        )

    [18] => Array
        (
            [id] => 24
            [name] => Filosofi
            [parent] => 1
            [depth] => 1
        )

)

Я хочу массив таким образом (после сортировки):

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Kompetenser
            [parent] => 0
            [depth] => 0
        )

    [1] => Array
        (
            [id] => 2
            [name] => Administration
            [parent] => 1
            [depth] => 1
        )

    [3] => Array
        (
            [id] => 4
            [name] => Arbetsledning
            [parent] => 2
            [depth] => 2
        )

    [2] => Array
        (
            [id] => 11
            [name] => Organisation
            [parent] => 2
            [depth] => 2
        )

    [4] => Array
        (
            [id] => 17
            [name] => Planering
            [parent] => 2
            [depth] => 2
        )

    [12] => Array
        (
            [id] => 18
            [name] => Apotekare
            [parent] => 1
            [depth] => 1
        )

    [13] => Array
        (
            [id] => 19
            [name] => Dotkorand
            [parent] => 1
            [depth] => 1
        )

    [14] => Array
        (
            [id] => 21
            [name] => Atomfysik
            [parent] => 19
            [depth] => 2
        )

    [15] => Array
        (
            [id] => 20
            [name] => Fysik
            [parent] => 19
            [depth] => 2
        )

    [16] => Array
        (
            [id] => 22
            [name] => Ekonom
            [parent] => 1
            [depth] => 1
        )

    [17] => Array
        (
            [id] => 23
            [name] => Industriell ekonomi
            [parent] => 22
            [depth] => 2
        )

    [18] => Array
        (
            [id] => 24
            [name] => Filosofi
            [parent] => 1
            [depth] => 1
        )

    [5] => Array
        (
            [id] => 9
            [name] => Hantverke
            [parent] => 1
            [depth] => 1
        )

    [6] => Array
        (
            [id] => 10
            [name] => Snickeri
            [parent] => 9
            [depth] => 2
        )

    [7] => Array
        (
            [id] => 12
            [name] => Språk
            [parent] => 1
            [depth] => 1
        )

    [8] => Array
        (
            [id] => 13
            [name] => Tolk
            [parent] => 12
            [depth] => 2
        )

    [9] => Array
        (
            [id] => 15
            [name] => Arabiska
            [parent] => 13
            [depth] => 3
        )


    [10] => Array
        (
            [id] => 14
            [name] => Persiska
            [parent] => 13
            [depth] => 3
        )

    [11] => Array
        (
            [id] => 16
            [name] => Polska
            [parent] => 13
            [depth] => 3
        )

)

Как вы можете видеть, я хочу, чтобы все посты с родителем 2 сразу после поста с идентификатором 2 и т. Д.

Любая помощь будет принята с благодарностью. Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 17 мая 2009

Не делайте этого в PHP!

Сервер MySQL специально разработан для запроса и сортировки данных, считанных по синтаксису MySQL « ORDER BY ». Делая это на сервере MySQL, вы сэкономите время выполнения, загрузку процессора и потребление памяти.

2 голосов
/ 17 мая 2009

Используйте функцию php's uasort() для определения собственной функции сравнения.

Но использование возможностей сортировки MySQL было бы более уместным, если это возможно в вашем случае.

0 голосов
/ 19 мая 2009

Проблема решена - я сделал две простые функции. Я надеюсь, что другие люди могли бы также использовать это:

class data_comp
{
    var $fetched_tree = array();

    function tree_fetch($parent = 0)
    {
        $query = 'SELECT node.id, node.name, node.parent, (COUNT(parent.name) - 1) AS depth FROM test_competence AS node, test_competence AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.name';
        $result = mysql_query($query) or die(mysql_error());
        $tree = array();

        while($data = mysql_fetch_assoc($result))
        {
            $tree[$data['parent']][$data['id']] = array('name' => $data['name'], 'depth' => $data['depth']);
        }

        $this->tree_print($tree, $parent);
    }

    function tree_print($tree, $parent)
    {
        foreach($tree[$parent] as $id => $value)
        {
            $this->fetched_tree[] = array('id' => $id, 'name' => $value['name'], 'depth' => $value['depth']);

            if(isset($tree[$id]) && is_array($tree[$id]))
            {
                $this->tree_print($tree, $id);
            }
        }
    }
}

Спасибо за ваше время. Любые улучшения приветствуются.

0 голосов
/ 18 мая 2009

Вы хотите отсортировать его как в БД, многослойный. Я не думаю, что uasort может помочь с этой проблемой, потому что вы хотите прикрепить детей к родителю.

foreach ($arr as &$val) {
    $arr2[$val['id']] = &$val;
}

ksort($arr2);

foreach ($arr2 as $id => &$val) {
    $parent = $val['parent'];
    if ($parent == 0) {
        continue;
    }
    $arr2[$parent]['children'][$id] = &$val;
}

function flattenArrayByChildren($arr) {
    foreach ($arr as $id => $val) {
        if (isset($val['children'])) {
            $temp = flattenArrayByChildren($val['children']);
            unset($val['children']);
            $out[$id] = $val;
            $out = $out + $temp;
        } else {
            $out[$id] = $val;
        }
    }
    return $out;
}

$arr2 = array(1 => $arr2[1]);

$out = flattenArrayByChildren($arr2);

var_dump($out);

Если вы абсолютно хотите сохранить ключ, вы можете просто добавить его к $ val в первом foreach и извлечь его в рекурсивной функции flattenArrayByChildren и использовать в качестве ключа.

...