我如何组合对象属性在一个数组中有一个共同的属性在javascript



我有以下用户信息:

[ { ID: '21',NAME: 'JACK',MARKS: 75,GRADE: 'A',RESULT: 'PASS ' },
{ ID: '21',NAME: 'JACK',MARKS: 32,GRADE: 'F',RESULT: 'FAIL' },
{ ID: '87',NAME: 'SAM',MARKS: 91,GRADE: 'A+',RESULT: 'PASS' },
{ID: '7',NAME: 'TOM',MARKS: 100,GRADE: 'A+',RESULT: 'PASS' },
{ ID: '21',NAME: 'JACK',MARKS: 61,GRADE: 'B',RESULT: 'PASS' },
{ ID: '87',NAME: 'SAM',MARKS: 72,GRADE: 'B',RESULT: 'PASS ' }
]

目标是生成一个名为INFO的新对象,其中包含MARKS,GRADE,RESULT字段。此外,由于存在重复的id,因此INFO属性需要与其各自的id分组,并生成以下结果

[{ID:'21',INFO:[{MARKS: 75,GRADE: 'A',RESULT: 'PASS ' },{MARKS: 32,GRADE: 'F',RESULT: 'FAIL'},{MARKS: 61,GRADE: 'B',RESULT: 'PASS']},
{ID:'87',INFO:[MARKS: 91,GRADE: 'A+',RESULT: 'PASS'],[MARKS: 72,GRADE: 'B',RESULT: 'PASS ']},
{ID:'7',INFO:{ MARKS: 100,GRADE: 'A+,RESULT: 'PASS'}
]

我试图使用下面的代码,但它没有产生预期的结果

console.log(groupByField(data,'id'))
function groupByField(data, field) {
var outObject = data.reduce(function (a, e) {
let estKey = (e[field]);
(a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
return a;
}, {});
return outObject
}

有人能帮帮我吗?


function transform(info) {
return info.reduce((pre, cur) => {
let ext = pre.find(d => d.ID === cur.ID);
let {ID, MARKS, GRADE, RESULT} = cur;
if (ext) {
ext.INFO = ext.INFO instanceof Array 
? [...ext.INFO, {MARKS, GRADE, RESULT}]
: [ext.INFO, {MARKS, GRADE, RESULT}];
} else {
pre.push({ID, INFO:{MARKS, GRADE, RESULT}});
}
return pre;
}, []);
}

编码快乐!

您可以使用Map和forEach

实现所需的结果

const arr = [
{ ID: "21", NAME: "JACK", MARKS: 75, GRADE: "A", RESULT: "PASS " },
{ ID: "21", NAME: "JACK", MARKS: 32, GRADE: "F", RESULT: "FAIL" },
{ ID: "87", NAME: "SAM", MARKS: 91, GRADE: "A+", RESULT: "PASS" },
{ ID: "7", NAME: "TOM", MARKS: 100, GRADE: "A+", RESULT: "PASS" },
{ ID: "21", NAME: "JACK", MARKS: 61, GRADE: "B", RESULT: "PASS" },
{ ID: "87", NAME: "SAM", MARKS: 72, GRADE: "B", RESULT: "PASS " },
];
const map = new Map();
arr.forEach((o) => {
const { ID, NAME, ...rest } = o;
if (map.has(o.ID)) map.get(o.ID).push(rest);
else map.set(o.ID, [rest]);
});
const result = [];
for (let [ID, INFO] of map) {
if (INFO.length === 1) result.push({ ID, INFO: INFO[0] });
else result.push({ ID, INFO });
}
console.log(result);

以下是对标记副本的重构,以满足您的特定需求,特别是在每个对象的嵌套数组中进行分组。

这是一个相当标准的"group-by",使用Array.prototype.reduce()和解构赋值相结合,只分离出我们需要的属性。

const input = [ { ID: '21', NAME: 'JACK', MARKS: 75, GRADE: 'A', RESULT: 'PASS ' }, { ID: '21', NAME: 'JACK', MARKS: 32, GRADE: 'F', RESULT: 'FAIL' }, { ID: '87', NAME: 'SAM', MARKS: 91, GRADE: 'A+', RESULT: 'PASS' }, { ID: '7', NAME: 'TOM', MARKS: 100, GRADE: 'A+', RESULT: 'PASS' }, { ID: '21', NAME: 'JACK', MARKS: 61, GRADE: 'B', RESULT: 'PASS' }, { ID: '87', NAME: 'SAM', MARKS: 72, GRADE: 'B', RESULT: 'PASS ' }, ];
const result = Object.values(
input.reduce(function (r, { ID, NAME, ...rest }) {
(r[ID] ??= { ID, INFO: [] }).INFO.push(rest);
return r;
}, Object.create(null))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

上面的代码片段使用了逻辑空赋值(??=)。为了兼容性,如果需要,您可以使用||短路代替。
(r[ID] || (r[ID] = { ID, INFO: [] })).INFO.push(rest);

使用lodashgroupBy(): https://lodash.com/docs/4.17.15#groupBy

const data = [
{ ID: '21', NAME: 'JACK', MARKS: 75, GRADE: 'A', RESULT: 'PASS ' },
{ ID: '21', NAME: 'JACK', MARKS: 32, GRADE: 'F', RESULT: 'FAIL' },
{ ID: '87', NAME: 'SAM', MARKS: 91, GRADE: 'A+', RESULT: 'PASS' },
{ ID: '7', NAME: 'TOM', MARKS: 100, GRADE: 'A+', RESULT: 'PASS' },
{ ID: '21', NAME: 'JACK', MARKS: 61, GRADE: 'B', RESULT: 'PASS' },
{ ID: '87', NAME: 'SAM', MARKS: 72, GRADE: 'B', RESULT: 'PASS ' },
];
const grouped = _.groupBy(data, 'NAME');

结果:

grouped:,  {
JACK: [
{ ID: '21', NAME: 'JACK', MARKS: 75, GRADE: 'A', RESULT: 'PASS ' },
{ ID: '21', NAME: 'JACK', MARKS: 32, GRADE: 'F', RESULT: 'FAIL' },
{ ID: '21', NAME: 'JACK', MARKS: 61, GRADE: 'B', RESULT: 'PASS' }
],
SAM: [
{ ID: '87', NAME: 'SAM', MARKS: 91, GRADE: 'A+', RESULT: 'PASS' },
{ ID: '87', NAME: 'SAM', MARKS: 72, GRADE: 'B', RESULT: 'PASS ' }
],
TOM: [ { ID: '7', NAME: 'TOM', MARKS: 100, GRADE: 'A+', RESULT: 'PASS' } ]
}

转换的方法,收集单个reduce任务中的项和没有额外的迭代在每个reduce步骤中可能看起来类似于下面的一个…

function groupCollectAndTransformItemById(collector, { ID, NAME, ...rest }) {
const { index, list } = collector;
let infoGroup = index[ID]?.INFO
if (Array.isArray(infoGroup)) {
// push into an already existing grouped array.
infoGroup.push(rest);
} else if (infoGroup) {
// create an array for more than just one grouped item.
index[ID].INFO = [infoGroup, rest];
} else {
// create a new group-item with
// its initial ID and first INFO data ...
infoGroup = index[ID] = { ID, INFO: rest };
// ... and push a reference into the collector's/
// accumulator's `list` array which also holds
// the final result of the reduce process.
list.push(infoGroup);
}
return collector;
}
const sampleData = [
{ ID: '21',NAME: 'JACK', MARKS: 75, GRADE: 'A', RESULT: 'PASS' },
{ ID: '21',NAME: 'JACK', MARKS: 32, GRADE: 'F', RESULT: 'FAIL' },
{ ID: '87',NAME: 'SAM', MARKS: 91, GRADE: 'A+', RESULT: 'PASS' },
{ ID: '7', NAME: 'TOM', MARKS: 100, GRADE: 'A+', RESULT: 'PASS' },
{ ID: '21',NAME: 'JACK', MARKS: 61, GRADE: 'B', RESULT: 'PASS' },
{ ID: '87',NAME: 'SAM', MARKS: 72, GRADE: 'B', RESULT: 'PASS' },
];
console.log(
sampleData
.reduce(groupCollectAndTransformItemById, {
index: {},
list: [],
}).list
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

相关内容

最新更新