Reputation: 83
My object which maps student id with marks is as follows:
[
{id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
{id: 222},
{id: 333, marks: []},
{id: 444, marks: [{sub: 'eng', mark: 70}]}
]
I would like to reduce it as follows:
{
marks[0]: "0:eng:90", // studentIndex:subject_name:mark
marks[1]: "0:maths:20",
marks[2]: "3:eng:70"
}
In the above result, the key is "marks[]" and the value is a string which is a concatenation of studentIndex, the subject and the mark. So here 0:eng:90 means that student with index of 0 has obtained 90 marks in english subject
I am using lodash and I have tried the following:
reduce(studentList, (acc, student, studentIndex) => {
map(get(student, 'marks'), (marks) => {
acc[`marks[${keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
});
return acc;
}, {});
Is there any other better way to do this?
Upvotes: 3
Views: 105
Reputation: 193248
With lodash you can iterate the students with _.flatMap()
, and map the students' marks to pairs of [key, value]. To generate the key you can use _.uniqueId()
. The end result would be an array of pairs, which you can convert to an object with _.fromPairs()
:
const studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
const result = _.fromPairs( // convert the array to an object
_.flatMap(studentList, ({ marks }, sIndex) => // iterate the students
_.map(marks, ({ sub, mark }) => [ // iterate the marks
`marks${_.uniqueId() - 1}`, // generate the key
`${sIndex}:${sub}:${mark}` // generate the value
])
)
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Upvotes: 0
Reputation: 5960
Another shorter way without lodash using map
:
var studentList = [
{id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
{id: 222},
{id: 333, marks: []},
{id: 444, marks: [{sub: 'eng', mark: 70}]}
];
var ac = {};
studentList.map((student, i) => {
if (student.marks && student.marks.length)
student.marks.map(m => ac[`marks[${Object.keys(ac).length}]`] = `${i}:${m.sub}:${m.mark}`);
});
console.log(ac);
Upvotes: 0
Reputation: 7899
You can use forEach
loop.
const input = [
{id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
{id: 222, marks: []},
{id: 333, marks: []},
{id: 444, marks: [{sub: 'eng', mark: 70}]}
];
const output = [];
input.forEach(({marks}, i) => {
marks.forEach(({sub, mark}) => {
output.push(`${i}:${sub}:${mark}`);
});
});
console.log(output);
--Edit--
const input = [
{id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
{id: 222},
{id: 333, marks: []},
{id: 444, marks: [{sub: 'eng', mark: 70}]}
];
const output = {};
let count = 0;
input.forEach((obj, i) => {
if(obj.hasOwnProperty("marks")) {
obj.marks.forEach(({sub, mark}) => {
output[`marks[${count}]`] = `${i}:${sub}:${mark}`;
count++;
});
}
});
console.log(output);
Upvotes: 2
Reputation: 20039
Without Lodash
var studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
var result = studentList.reduce((acc, student, studentIndex) => {
(student.marks || []).map((marks) => {
acc[`marks[${Object.keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
});
return acc;
}, {});
console.log(result)
With Lodash
var studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
var result = _.reduce(studentList, (acc, student, studentIndex) => {
_.map(student.marks || [], (marks) => {
acc[`marks[${_.keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
});
return acc;
}, {});
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Upvotes: 2