Deepa Sajani Jeyaraj
Deepa Sajani Jeyaraj

Reputation: 83

How do we reduce nested arrays?

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

Answers (4)

Ori Drori
Ori Drori

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

shrys
shrys

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

random
random

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

User863
User863

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

Related Questions