jacky
jacky

Reputation: 524

javascript optimize multiple reduce and map to extract data from nested objects

I am extracting some data out of an array of nested objects, using two reducees, and map, which is working at the moment, but it is a bit ugly. How can this be optimized?

function extractSchools(schools) {
  let schoolData = [];

  if (schools) {
    schoolData = schools.reduce(function(parentdata, chlrn) {
      let childrenlist = chlrn.children;
      let childrendata = [];

      if (childrenlist) {
        childrendata = childrenlist.reduce(function(addrsslist, school) {
          return addrsslist.concat(school.address.map(i => i.school));
        }, []);
      }

      return parentdata.concat(chlrn.parent, childrendata);
    }, []);
  }

  return {
    schoolData
  };
}

const schools = [{
    "parent": "Thomas Jefferson",
    "children": [{
        "address": [{
          "school": "School A"
        }]
      },
      {
        "address": [{
          "school": "School B"
        }]
      }
    ]
  },
  {
    "parent": "Jack Chan",
    "children": [{
      "address": [{
        "school": "School C"
      }]
    }]
  }
];


console.log(extractSchools(schools));

How can I optimize this function to get the same results? using one reduce instead of two... or some other optimal way of doing it.

Upvotes: 0

Views: 222

Answers (2)

prabhatojha
prabhatojha

Reputation: 2085

Try this, the result is little different than what you are expecting, but this will be a more generic way where you will have addresses with respect to school.

schools.map(p => {
    return {[p.parent]: p.children.map(c => c.address.map(add => add.school))}
})


[
  {
    "Thomas Jefferson": [
      [
        "School A"
      ],
      [
        "School B"
      ]
    ]
  },
  {
    "Jack Chan": [
      [
        "School C"
      ]
    ]
  }
]

Upvotes: 1

Csaba
Csaba

Reputation: 419

You can remove the if (childrenlist) { and use a pre-filter.

function extractSchools(schools) {
  let schoolData = [];

  if (schools) {
    schoolData = schools
      .filter(data => data.children)
      .reduce((parentdata, chlrn) => {
        const childrendata = chlrn.children.reduce(
          (addrsslist, school) =>
            addrsslist.concat(school.address.map(i => i.school)),
          []
        );
        return parentdata.concat(chlrn.parent, childrendata);
      }, []);
  }

  return { schoolData };
}

const schools = [
  {
    parent: "Thomas Jefferson",
    children: [
      {
        address: [
          {
            school: "School A"
          }
        ]
      },
      {
        address: [
          {
            school: "School B"
          }
        ]
      }
    ]
  },
  {
    parent: "Jack Chan",
    children: [
      {
        address: [
          {
            school: "School C"
          }
        ]
      }
    ]
  }
];

console.log(extractSchools(schools));

Upvotes: 1

Related Questions