2

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.

1
  • Siva Pradhan did u see answer below? Commented Apr 19, 2021 at 19:01

2 Answers 2

3

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);

Sign up to request clarification or add additional context in comments.

1 Comment

It worked perfectly. Thank you so much. :)
-1

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);

5 Comments

for the below input your answer won't be unique per apple name (u will have 2 entries of alpha apple which i believe is not good): const apple = [ { name: 'alpha', details: [{ attachment: [123, 456] }, { attachment: [1454, 1992] }] }, { name: 'alpha', details: [{ attachment: [123, 456, 222] }, { attachment: [1454, 1992] }] }, { name: 'beta', details: [ { attachment: ['12', 189] }, { attachment: ['maggi', 1890, 2000] }, { attachment: [1990, 2001, 2901] }, { attachment: [1990, 2001, 2901] }, ], }, ];
@LiorKaminsky, Yes, you are correct. If in case of OP can have multiple entries for alpha then he should better go with solution that you have provided.
The output seems different to what OP expects. This will create an object for each sum and return an array. OP expects a single object with the names as key and the count as values.
@VLAZ, thanks for pointing that out. Updated answer.
I'm personally not a big fan of continually spreading objects with reduce(). I'd probably go for making resultArr an array of pairs, then just use Object.fromEntries() on it: jsbin.com/kinayot/edit?js,console Another alternative is with your current code to call resultArr.reduce((i, a) => Object.assign(i, a), {})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.