Пример простой, но он поможет мне решить сложную проблему для таблицы данных, созданной с помощью angular и material, которая получает массив. Я получаю массив объектов, которые я хочу организовать по происхождению, как следующий пример, который я представляю в простой форме, чтобы не запутывать вопрос со сложными данными.
Я получаю данные как array1:
array1 = [
{id:1, parent_id:0, data:'txt'},
{id:2, parent_id:0, data:'txt'},
{id:3, parent_id:1, data:'txt'},
{id:4, parent_id:1, data:'txt'},
{id:5, parent_id:0, data:'txt'},
{id:6, parent_id:0, data:'txt'},
{id:7, parent_id:5, data:'txt'},
];
и я хочу организовать его как array2.
array2 = [
{id:1, parent_id:0, data:'txt'},
{id:3, parent_id:1, data:'txt'},
{id:4, parent_id:1, data:'txt'},
{id:2, parent_id:0, data:'txt'},
{id:5, parent_id:0, data:'txt'},
{id:7, parent_id:5, data:'txt'},
{id:6, parent_id:0, data:'txt'},
];
Чем массив2 отличается от массива1? Я имею в виду, как именно вы хотите организовать?
А что вы пробовали?
Знакомы ли вы с понятиями поиска в глубину и/или топологической сортировки?
Для всех, кто просит разъяснений о том, как именно было сформировано array2
, нарисуйте подразумеваемое дерево (поле parent_id
— это идентификатор родителя), затем выполните поиск в глубину, и вы получите именно array2
.
Здесь у вас есть одно возможное решение, использующее сначала Массив.фильтр() для получения объектов без родителей (то есть объектов, где parent_id:0
), а затем сортировать их с помощью свойства id
. После этого мы используем Массив.уменьшить(), чтобы получить список дочерних элементов для каждого из предыдущих объектов, отсортировать эти дочерние элементы и поместить их сразу после его родителя. Однако это не эффективное решение, возможно, есть лучшие варианты.
const array1 = [
{id:1, parent_id:0, data:'txt'},
{id:2, parent_id:0, data:'txt'},
{id:3, parent_id:1, data:'txt'},
{id:4, parent_id:1, data:'txt'},
{id:5, parent_id:0, data:'txt'},
{id:6, parent_id:0, data:'txt'},
{id:7, parent_id:5, data:'txt'},
];
let res = array1
.filter(({parent_id}) => parent_id === 0)
.sort((a, b) => a.id - b.id)
.reduce((acc, curr) =>
{
const children = array1
.filter(({parent_id}) => parent_id === curr.id)
.sort((a, b) => a.id - b.id);
return [...acc, curr, ...children];
}, []);
console.info(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Решение исходит из аналогичного вопроса, который я задал некоторое время назад, вы также можете проверить там другие ответы и мой первый подход (лучше по производительности, но не общий, у него были некоторые ограничения, как описано там) для решения такой проблемы: Сортировка массива категорий и подкатегорий
Какова логика сортировки второго массива?