Count array inside array of object

Viewed 168

Suppose I have an array of Object as:

Expected O/P : {alpha:4, beta:8}

For this I tried as:

const apple = [{
    name: 'alpha',
    details: [{
      "attachment": [123, 456]
    }, {
      "attachment": [1454, 1992]
    }]
  },
  {
    name: 'beta',
    details: [{
      "attachment": ["12", 189]
    }, {
      "attachment": ["maggi", 1890, 2000]
    }, {
      "attachment": [1990, 2001, 2901]
    }]
  }
];

const appleDetails = [];

for (let i = 0; i < apple.length; i++) {
  for (let j = 0; j < apple[i].details.length; j++) {
    const {
      name
    } = apple[i];
    const {
      attachment
    } = apple[i].details[j]
    appleDetails.push({
      name,
      attachment
    })
  }
}

let appleData = [];
appleDetails.forEach(({
  name,
  attachment
}) => {
  attachment.forEach((attatchId) => {
    appleData.push({
      name,
      _id: attatchId
    })
  })
})

const eachAppleCount = appleData.reduce((acc, item) => {
  const key = item.name
  if (!acc.hasOwnProperty(key)) {
    acc[key] = 0
  }
  acc[key] += 1
  return acc
}, {})

console.log(eachAppleCount);

This gives the O/P as required i.e. : {alpha:4, beta:8}

But the process involved is too much, is there any more efficient way such that,by using:

const apple = [{
    name: 'alpha',
    details: [{
        "attachment": [123, 456]
    }, {
        "attachment": [1454, 1992]
    }]
}, {
    name: 'beta',
    details: [{
        "attachment": ["12", 189]
    }, {
        "attachment": ["maggi", 1890, 2000]
    }, {
        "attachment": [1990, 2001, 2901]
    }]
}];

We can count the value for each apple name. If anyone needs any further information please do let me know.

2 Answers

This will do the work

const apple = [{
  name: 'alpha',
  details: [{
    "attachment": [123, 456]
  }, {
    "attachment": [1454, 1992]
  }]
}, {
  name: 'beta',
  details: [{
    "attachment": ["12", 189]
  }, {
    "attachment": ["maggi", 1890, 2000]
  }, {
    "attachment": [1990, 2001, 2901]
  }]
}];

const result = apple.reduce((acc, curr) => {
  if (acc[curr.name] === undefined) acc[curr.name] = 0;
  curr.details.forEach((d) => (acc[curr.name] += d.attachment.length));
  return acc;
}, {});

console.log(result);

Try like below.

  • Array.prototype.map() - The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
  • Create new object as {[a.name]: values} where we use [a.name] inside [] so value from a.name will be set as object key.
  • To get value we use Array.prototype.flatMap() - The flatMap() method returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.
  • Get all attachments with a.details.flatMap(d => d.attachment) and use .length to get total count as value.
  • map will return result in format of array of objects.
  • Use Array.prototype.reduce() with spread syntax (...) to club array of objects into single object.

const apple = [
               { name: 'alpha', details: [{"attachment": [ 123, 456 ]}, {"attachment": [1454, 1992 ]} ]},
               {name: 'beta', details: [{"attachment": [ "12", 189 ]},{"attachment": ["maggi", 1890,2000 ]}, {"attachment": [1990, 2001,2901 ]} ]}
              ];

// map will return result in format of array of objects
let resultArr = apple.map(a => ({[a.name]: a.details.flatMap(d => d.attachment).length }));

// use reduce with spread syntax (...) to club array of objects into single object.
let result = resultArr.reduce((i, a) => ({...a, ...i}), {});

console.log(result);

Related