Я немного застрял в этом: у меня есть массив объектов, упорядоченных по иерархии (parent_id
), что-то вроде:
let myArray = [
{ id: 1, parent_id: null, score: 20, type: 1 },
{ id: 12, parent_id: 1, score: 25, type: 2 },
{ id: 23, parent_id: 12, score: 55, type: 3 },
{ id: 35, parent_id: 12, score: 25, type: 3 },
{ id: 10, parent_id: null, score: 75, type: 1 },
{ id: 25, parent_id: 10, score: 15, type: 2 },
{ id: 100, parent_id: 25, score: 88, type: 3 }
]
Теперь я хотел бы сохранить порядок иерархии, но также упорядочить элементы по результату, чтобы получить что-то вроде этого:
let expected = [
{ id: 10, parent_id: null, score: 75, type: 1 },
{ id: 25, parent_id: 10, score: 15, type: 2 },
{ id: 100, parent_id: 25, score: 88, type: 3 },
{ id: 1, parent_id: null, score: 20, type: 1 },
{ id: 12, parent_id: 1, score: 25, type: 2 },
{ id: 23, parent_id: 12, score: 55, type: 3 },
{ id: 35, parent_id: 12, score: 25, type: 3 },
]
Я пишу довольно неэффективный код с вложенным foreach
который почти работает, но и не совсем. Мне было интересно, есть ли более аккуратное решение. (довольно уверен, что есть, но слишком умный для меня). Также в моем коде я передаю атрибут type
, но в идеале я бы не использовал его для сортировки.
Примечание. Эти данные являются всего лишь примером, реальный массив больше и число детей для каждого родителя меняется.
Поскольку мои объяснения не велики, мы можем думать об иерархии таким образом type:1
→ type:2
страны type:2
→ type:3
государства type:3
→ Город
Так что мне нужно заказать по desc
как это
- Country
- State
- City
- City
- State
- City
- Country and so on...
Спасибо всем, кто готов принести мне руку,
Один вид не работает из-за отношения родительских детей, которое не соблюдается при сортировке данных.
Этот подход работает в трех частях:
score
, так как следующее дерево создается в порядке вставки.
var data = [{ id: 1, parent_id: null, score: 20, type: 1 }, { id: 12, parent_id: 1, score: 25, type: 2 }, { id: 23, parent_id: 12, score: 55, type: 3 }, { id: 35, parent_id: 12, score: 25, type: 3 }, { id: 10, parent_id: null, score: 75, type: 1 }, { id: 25, parent_id: 10, score: 15, type: 2 }, { id: 100, parent_id: 25, score: 88, type: 3 }]
.sort(function (a, b) { return b.score - a.score; }),
tree = function (data, root) {
var r = [], o = {};
data.forEach(function (a) {
o[a.id] = { data: a, children: o[a.id] && o[a.id].children };
if (a.parent_id === root) {
r.push(o[a.id]);
} else {
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || [];
o[a.parent_id].children.push(o[a.id]);
}
});
return r;
}(data, null), // null is the root value of parent_id
sorted = tree.reduce(function traverse(r, a) {
return r.concat(a.data, (a.children || []).reduce(traverse, []));
}, [])
console.log(sorted);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
id
или parent_id
имеют другое имя.
Я изменил свой набор данных, чтобы сделать этот пример более понятным. И я использовал несколько функций для сортировки данных:
let arr = [
{country: 'USA', state:'Washington', city:'Washington DC'},
{country: 'USA', state:'Washington', city:'Boston'},
{country: 'USA', state:'California', city:'San Diego'},
{country: 'Brazil', state:'North', city:'C'},
{country: 'Brazil', state:'North', city:'B'},
{country: 'Brazil', state:'South', city:'A'},
{country: 'Turkey', state:'East', city:'f'},
{country: 'Turkey', state:'East', city:'e'},
{country: 'Turkey', state:'West', city:'d'},
];
let expected = [
{country: 'Brazil', state:'North', city:'B'},
{country: 'Brazil', state:'North', city:'C'},
{country: 'Brazil', state:'South', city:'A'},
{country: 'Turkey', state:'East', city:'e'},
{country: 'Turkey', state:'East', city:'f'},
{country: 'Turkey', state:'West', city:'d'},
{country: 'USA', state:'California', city:'San Diego'},
{country: 'USA', state:'Washington', city:'Boston'},
{country: 'USA', state:'Washington', city:'Washington DC'},
];
const sortByCountry = arr => {
return arr.sort((city1,city2) => city1.country > city2.country);
};
const sortByState = arr =>
arr.sort(
(city1,city2) => {
// Don't compare when countries differ.
if (city1.country !== city2.country) return 0;
return city1.state > city2.state;
}
);
const sortByCity = arr =>
arr.sort(
(city1,city2) => {
// Don't compare when countries or states differ.
if (city1.country !== city2.country) return 0;
if (city1.state !== city2.state) return 0;
return city1.city > city2.city;
}
);
let result = sortByCity(sortByState(sortByCountry(arr)));
console.log('------expected-----');
console.log(expected);
console.log('------result-----');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }