[英]Group Array of Objects of same level
I have an array which has different level of approvers.我有一个具有不同级别批准者的数组。 I need to combine the object of similar level and group them with the Name+counter.我需要组合相似级别的对象并将它们与名称+计数器分组。
"APPROVERS": [
{
"LEVEL": "L5",
"EMAIL": "FTEST@TEST.COM",
"FULLNAME": "FNAME",
"POSITION": "FPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L4",
"EMAIL": "JTEST@TEST.COM",
"FULLNAME": "JNAME",
"POSITION": "JPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L5",
"EMAIL": "LTEST@TEST.COM",
"FULLNAME": "LNAME",
"POSITION": "GPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L5",
"EMAIL": "TTEST@TEST.COM",
"FULLNAME": "TNAME",
"POSITION": "CPOS",
"SLA": "48",
"STATUS": "INITIAL"
}
]
I need to combine the objects of same level into one and provide the unique name.我需要将相同级别的对象合并为一个并提供唯一名称。
"APPROVERS": [
{
"LEVEL": "L5",
"EMAIL1": "FTEST@TEST.COM",
"FULLNAME1": "FNAME",
"POSITION1": "FPOS",
"SLA1": "48",
"STATUS1": "INITIAL",
"EMAIL2": "LTEST@TEST.COM",
"FULLNAME2": "LNAME",
"POSITION2": "GPOS",
"SLA2": "48",
"STATUS2": "INITIAL",
"EMAIL3": "TTEST@TEST.COM",
"FULLNAME3": "TNAME",
"POSITION3": "CPOS",
"SLA3": "48",
"STATUS3": "INITIAL"
},
{
"LEVEL": "L4",
"EMAIL": "JTEST@TEST.COM",
"FULLNAME": "JNAME",
"POSITION": "JPOS",
"SLA": "48",
"STATUS": "INITIAL"
}
]
I tried only to combine EMAIL by looping the array but not able to achieve the result.Kindly suggest.我只尝试通过循环数组来组合 EMAIL,但无法实现结果。请建议。
var result = [];
var i=0
APPROVERS.forEach(function(obj) {
var id = obj.LEVEL
if(!this[id]) result.push(this[id] = obj);
else this[id].EMAIL += obj.EMAIL+i;
i++;
}, Object.create(null));
console.log(result)
You can do this by grouping the elements of the same level in an object associating levels with an array of elements, like so:您可以通过将级别与元素数组关联的对象中的同一级别的元素进行分组来完成此操作,如下所示:
{
"L5": [
{
"EMAIL": "FTEST@TEST.COM",
"FULLNAME": "FNAME",
"POSITION": "FPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
...
],
"L4": [
{
"EMAIL": "JTEST@TEST.COM",
"FULLNAME": "JNAME",
"POSITION": "JPOS",
"SLA": "48",
"STATUS": "INITIAL"
}
]
}
Then iterate over the levels and create an array of unique levels which hold each elements with their unique set of keys EMAIL{i}
, FULLNAME{i}
, POSITION{i}
, SLA{i}
and STATUS{i}
:然后迭代这些级别并创建一个唯一级别的数组,这些级别包含每个元素及其唯一的键EMAIL{i}
、 FULLNAME{i}
、 POSITION{i}
、 SLA{i}
和STATUS{i}
:
[
{
"LEVEL": "L5",
"EMAIL1": "FTEST@TEST.COM",
"FULLNAME1": "FNAME",
"POSITION1": "FPOS",
"SLA1": "48",
"STATUS1": "INITIAL",
...
},
{
"LEVEL": "L4",
"EMAIL1": "JTEST@TEST.COM",
"FULLNAME1": "JNAME",
"POSITION1": "JPOS",
"SLA1": "48",
"STATUS1": "INITIAL"
}
]
Here is the full code:这是完整的代码:
// prepare an intermediate representation of your data { level => approver[] } const grouped = data['APPROVERS'].reduce((approvers, approver) => { const { LEVEL, ...props } = approver; approvers[LEVEL] = approvers[LEVEL] ? approvers[LEVEL].concat([props]) : [props] return approvers; }, {}) // helper function to append a suffix to all keys of a given object const suffixKeys = (obj, suffix) => { return Object.entries(obj).reduce((result, [key, value]) => { return { ...result, [key+suffix]: value } }, {}); } // combine the objects into an array using the intermediate representation const result = Object.entries(grouped).map(([name, group]) => { return group.reduce((grouped, current, i) => { return { ...grouped, ...suffixKeys(current, i+1) } }, { LEVEL: name }); }); console.log(result)
<script>const data={APPROVERS:[{LEVEL:"L5",EMAIL:"FTEST@TEST.COM",FULLNAME:"FNAME",POSITION:"FPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L4",EMAIL:"JTEST@TEST.COM",FULLNAME:"JNAME",POSITION:"JPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"LTEST@TEST.COM",FULLNAME:"LNAME",POSITION:"GPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"TTEST@TEST.COM",FULLNAME:"TNAME",POSITION:"CPOS",SLA:"48",STATUS:"INITIAL"}]};</script>
However, in my opinion, the intermediate format would be a lot easier to work with.但是,在我看来,中间格式会更容易使用。
By putting the tag lodash
I guess you don't mind using it.通过放置标签lodash
我猜你不介意使用它。 I'm not sure you understand it, but I've tried my best to balance between succinctness and readability .我不确定你是否理解它,但我已尽力在简洁性和可读性之间取得平衡。
function groupByLevel(approvers) { const group = _.groupBy(approvers, 'LEVEL'); // console.log(group); // try logging to see what we have return Object.entries(group).map( ([LEVEL, array]) => { return array.reduce((acc, cur, idx) => ({ ...acc, ['EMAIL' + (idx + 1)]: cur.EMAIL , ['FULLNAME' + (idx + 1)]: cur.FULLNAME , ['POSITION' + (idx + 1)]: cur.POSITION , ['SLA' + (idx + 1)]: cur.SLA , ['STATUS' + (idx + 1)]: cur.STATUS , }), { LEVEL }); }) } var APPROVERS = [ { LEVEL: 'L5', EMAIL: 'FTEST@TEST.COM', FULLNAME: 'FNAME', POSITION: 'FPOS', SLA: '48', STATUS: 'INITIAL' }, { LEVEL: 'L4', EMAIL: 'JTEST@TEST.COM', FULLNAME: 'JNAME', POSITION: 'JPOS', SLA: '48', STATUS: 'INITIAL' }, { LEVEL: 'L5', EMAIL: 'LTEST@TEST.COM', FULLNAME: 'LNAME', POSITION: 'GPOS', SLA: '48', STATUS: 'INITIAL' }, { LEVEL: 'L5', EMAIL: 'TTEST@TEST.COM', FULLNAME: 'TNAME', POSITION: 'CPOS', SLA: '48', STATUS: 'INITIAL' } ] console.log(groupByLevel(APPROVERS))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
The following algorithm achieves exactly what you want:以下算法完全符合您的要求:
let APPROVERS = [ { "LEVEL": "L5", "EMAIL": "FTEST@TEST.COM", "FULLNAME": "FNAME", "POSITION": "FPOS", "SLA": "48", "STATUS": "INITIAL" }, { "LEVEL": "L4", "EMAIL": "JTEST@TEST.COM", "FULLNAME": "JNAME", "POSITION": "JPOS", "SLA": "48", "STATUS": "INITIAL" }, { "LEVEL": "L5", "EMAIL": "LTEST@TEST.COM", "FULLNAME": "LNAME", "POSITION": "GPOS", "SLA": "48", "STATUS": "INITIAL" }, { "LEVEL": "L5", "EMAIL": "TTEST@TEST.COM", "FULLNAME": "TNAME", "POSITION": "CPOS", "SLA": "48", "STATUS": "INITIAL" } ]; var result = {}; var compareLevel = {}; for (let index = 0; index < APPROVERS.length; index++) { if(Object.keys(compareLevel).includes(APPROVERS[index].LEVEL)){ for (const key in APPROVERS[index]) { if(key == 'LEVEL') continue; let keyIndex = compareLevel[APPROVERS[index].LEVEL] + 1; result[APPROVERS[index].LEVEL][key + keyIndex] = APPROVERS[index][key]; } compareLevel[APPROVERS[index].LEVEL]++; }else{ result[APPROVERS[index].LEVEL] = APPROVERS[index]; compareLevel[APPROVERS[index].LEVEL] = 1; } } let resultArr = Object.values(result); console.log(Object.values(result));
I see that there are a lot of good answer here (that i will upvote), but as i promised, i deliver to you how i would taclke your problem.我看到这里有很多好的答案(我会赞成),但正如我所承诺的,我会告诉你我将如何解决你的问题。 Let me show the code让我展示一下代码
var theApprovers = [
{
"LEVEL": "L5",
"EMAIL": "FTEST@TEST.COM",
"FULLNAME": "FNAME",
"POSITION": "FPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L4",
"EMAIL": "JTEST@TEST.COM",
"FULLNAME": "JNAME",
"POSITION": "JPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L5",
"EMAIL": "LTEST@TEST.COM",
"FULLNAME": "LNAME",
"POSITION": "GPOS",
"SLA": "48",
"STATUS": "INITIAL"
},
{
"LEVEL": "L5",
"EMAIL": "TTEST@TEST.COM",
"FULLNAME": "TNAME",
"POSITION": "CPOS",
"SLA": "48",
"STATUS": "INITIAL"
}
]
function groupBy (collection, key) { // based on https://stackoverflow.com/a/34890276/903998
return collection.reduce(function(grouped, element) {
(grouped[element[key]] = grouped[element[key]] || []).push(element);
return grouped;
}, {});
};
function arrangeApprovers(approvers) {
// first group by level
var groupedByLevel = groupBy(approvers,"LEVEL")
// then for each level do the arrange as you need
var arrayOflevelWithApprovers = Object.keys(groupedByLevel).map(function(level) {
var approversOfSameLevel = groupedByLevel[level]
var levelWithApprovers = {"LEVEL" : level}
approversOfSameLevel.forEach(function(approber, index) {
var suffixNumber = index+1
levelWithApprovers["EMAIL"+suffixNumber] = approber["EMAIL"]
levelWithApprovers["FULLNAME"+suffixNumber] = approber["FULLNAME"]
levelWithApprovers["POSITION"+suffixNumber] = approber["POSITION"]
levelWithApprovers["SLA"+suffixNumber] = approber["SLA"]
levelWithApprovers["STATUS"+suffixNumber] = approber["STATUS"]
})
return levelWithApprovers
});
return arrayOflevelWithApprovers;
}
var theApproversArrenged = arrangeApprovers(theApprovers) // so they are arrangen in the convenient fashion..
console.log(theApproversArrenged)
https://repl.it/repls/TruthfulLivelyInterface https://repl.it/repls/TruthfulLivelyInterface
You could see that inside theAprroversArrenged
the elements are arranged in the fashion you need.您可以看到在theAprroversArrenged
,元素以您需要的方式排列。
Disclaimer do note that for level4 (and for those levels with an unique approver) the generated records will refer to his attributes with the suffix of 1. Hope that to not be something really annoying for your purposes.免责声明请注意,对于 level4(以及具有唯一批准者的那些级别),生成的记录将引用后缀为 1 的他的属性。希望这不会对您的目的造成真正的困扰。
After you group the array by LEVEL
, you can map the groups.按LEVEL
对数组进行分组后,您可以映射这些组。 Check the group's length.检查组的长度。 If it has a single item, you can return that item.如果它只有一个项目,您可以退回该项目。 If it has more than 1 one, you'll need to map the items, and map the keys of the items to include the item's index + 1, and then merge all items to a single object:如果超过 1 个,则需要映射项目,并将项目的键映射为包含项目的索引 + 1,然后将所有项目合并为单个对象:
const fn = (arr, groupKey) => { const groups = _.groupBy(arr, groupKey); return _.map(groups, group => group.length > 1 ? // if there's more than one item _.merge(... // merge all items _.map(group, (item, idx) => _.mapKeys( // map the items in the group item, (v, k) => k === groupKey ? k : `${k}${idx + 1}` // add the index to all keys, but LEVEL )) ) : group[0] ) }; const data = {APPROVERS:[{LEVEL:"L5",EMAIL:"FTEST@TEST.COM",FULLNAME:"FNAME",POSITION:"FPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L4",EMAIL:"JTEST@TEST.COM",FULLNAME:"JNAME",POSITION:"JPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"LTEST@TEST.COM",FULLNAME:"LNAME",POSITION:"GPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"TTEST@TEST.COM",FULLNAME:"TNAME",POSITION:"CPOS",SLA:"48",STATUS:"INITIAL"}]}; const result = fn(data.APPROVERS, 'LEVEL') console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.