简体   繁体   English

按分数排序数组,可能使用lodash。 (的NodeJS)

[英]Ordering array with hierarchy by score, possibly using lodash. (nodejs)

I am a bit stuck on this one: I have a array of objects ordered according to a hierarchy ( parent_id ), something as follow: 我有点困在这一个:我有一个根据层次结构( 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 }
]

Now I would like to maintain the hierarchy order, but also order the elements by score to obtain something like this: 现在我想维护层次结构顺序,还要按分数对元素进行排序以获得如下内容:

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 },
]

I am writing pretty inefficient code with nested foreach that almost work, but nor quite yet. 我正在编写非常低效的代码,嵌套的foreach几乎可以工作,但还没有完成。 I was wondering if there was a neater solution. 我想知道是否有更整洁的解决方案。 (pretty sure there is, but too smart for me). (很确定有,但对我来说太聪明了)。 Also in my code I am relaying on the type attribute, but ideally I would not use it for sorting. 同样在我的代码中我转发了type属性,但理想情况下我不会用它来进行排序。

Note: this data is just an example, the real array is bigger and the number of children for each parent vary. 注意:这个数据只是一个例子,真实数组更大,每个父项的子数变化。

Since my explanation is not great we can think of hierarchy in this way type:1 -> Country type:2 -> State type:3 -> City 由于我的解释不是很好,我们可以用这种方式思考层次结构type:1 - >国家type:2 - >州type:3 - >城市

So I need to order by score desc like this 所以我需要通过这样的得分desc来订购

- Country
  - State
    - City 
    - City
  - State
    - City
 - Country and so on...

Thank you to anyone who is willing to land me an hand, 感谢愿意帮助我的人,

A single sort does not work, because of the parent children relation which is not respected while sorting the data. 单个排序不起作用,因为在排序数据时不遵守父子关系。

This approach works in three parts: 这种方法分为三个部分:

  1. Sort data by score , because the following tree is build in insertation order. score对数据排序,因为以插入顺序构建了以下树。
  2. Build a tree with the given relationship. 用给定的关系构建一棵树。
  3. Traverse the tree and get sorted flat data back. 遍历树并返回已排序的平面数据。

 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; } 

I changed your data set to make the example easier to understand. 我更改了您的数据集以使示例更易于理解。 And I used several functions to sort the data: 我使用了几个函数来对数据进行排序:

 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; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM