1

So I have a data like this

const carts = [
  {
    name: 'Voucher A',
    participants: [
      {
        date: 112
      },
      {
        date: 112
      }
    ],
    supplierName: 'ABC',
    ticketDescription: 'Description of',
    ...data
  },
  {
    name: 'Voucher B',
    participants: [
      {
        date: 111
      },
      {
        date: 112
      }
    ],
    supplierName: 'ABC',
    ticketDescription: 'Description of',
    ...data
  }
]

And I want to group it based on the date (if it has same date). So for data above, the expected result will be

expected = [
  {
    name: 'Voucher A',
    date: 1,
    count: 1,
    supplierName: 'ABC',
    ticketDescription: 'Description of',
    ...data
  },
  {
    name: 'Voucher A',
    date: 2,
    count: 1,
    supplierName: 'ABC',
    ticketDescription: 'Description of',
    ...data
  }
]

Because it has different date. But if it has same date, the expected result will be

expected = [
  {
    name: 'Voucher A',
    date: 1,
    count: 2,
    supplierName: 'ABC',
    ticketDescription: 'Description of',
    ...data
  }
]

I was trying to use reduce to group it but it did not give the structure I want

carts.forEach(cart => {
  cart.participants.reduce((acc, obj) => {
    acc[obj.date] = [...acc[obj.date] || [], obj]
    return acc
  }, {})
})

3 Answers 3

1

To organize the data, I think you need two associations to group by: the name and the dates and their counts for that name:

const carts = [
  {
    name: 'Voucher A',
    participants: [
      {
        date: 1
      },
      {
        date: 2
      }
    ]
  }
];

const groupedByNames = {};
for (const { name, participants } of carts) {
  if (!groupedByNames[name]) groupedByNames[name] = {};
  for (const { date } of participants) {
    groupedByNames[name][date] = (groupedByNames[name][date] || 0) + 1;
  }
}
const output = Object.entries(groupedByNames).flatMap(
  ([name, dateCounts]) => Object.entries(dateCounts).map(
    ([date, count]) => ({ name, date: Number(date), count })
  )
);
console.log(output);

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

Comments

1

If you want use, just plain for loops, you can try this solution. It looks simple and elegant 😜😜

const carts = [
  {
    name: 'Voucher A',
    participants: [
      {
        date: 1
      },
      {
        date: 1
      },
      {
        date: 2
      }
    ]
  },
  {
    name: 'Voucher B',
    participants: [
      {
        date: 1
      },
      {
        date: 2
      },
      {
        date: 2
      }
    ]
  }
]

const finalOutput = []

for (const cart of carts) {
  for (const participant of cart.participants) {
     const res = finalOutput.find(e => e.name === cart.name && e.date === participant.date)
     if (res) {
        res.count += 1
     } else {
       finalOutput.push({ name: cart.name, date: participant.date, count: 1 })
     }
  }
}

console.log(finalOutput)

Comments

1

Use forEach and destructuring

const process = ({ participants, name }) => {
  const res = {};
  participants.forEach(({ date }) => {
    res[date] ??= { name, count: 0, date };
    res[date].count += 1;
  });
  return Object.values(res);
};


const carts = [
  {
    name: "Voucher A",
    participants: [
      {
        date: 1,
      },
      {
        date: 2,
      },
    ],
  },
];
console.log(carts.flatMap(process));

const carts2 = [
  {
    name: "Voucher A",
    participants: [
      {
        date: 1,
      },
      {
        date: 1,
      },
    ],
  },
];
console.log(carts2.flatMap(process));

Comments

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.