Skip to content

Create Array of Objects Based on 2 Arrays

I have an array, it looks like this.

const date = ['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05']

I have an array of objects, it looks like this.

const data = [
  {
    category: 'a',
    date: '2021-01-01',
    qty: '1'
  },
  {
    category: 'a',
    date: '2021-01-02',
    qty: '2'
  },
  {
    category: 'b',
    date: '2021-01-02',
    qty: '1'
  },
  {
    category: 'b',
    date: '2021-01-03',
    qty: '2'
  },
  {
    category: 'c',
    date: '2021-01-03',
    qty: '1'
  },
  {
    category: 'c',
    date: '2021-01-04',
    qty: '2'
  },
]

I want the result to be like this, the datasets’s length should be 5 (based on date’s length).

[
  {
    label: 'a',
    datasets: ['1', '2', '0', '0', '0']
  },
  {
    label: 'b',
    datasets: ['0', '1', '2', '0', '0']
  },
  {
    label: 'c',
    datasets: ['0', '0', '1', '2', '0']
  },
]

I tried code by myself, but the result looks like this

[
  {
    label: 'a',
    datasets: ['1', '2']
  },
  {
    label: 'b',
    datasets: ['1', '2']
  },
  {
    label: 'c',
    datasets: ['1', '2']
  },
]

Can anyone help me to code this?

Edit

const data = [
  {
    category: 'a',
    date: '2021-01-01',
    qty: '1'
  },
  {
    category: 'a',
    date: '2021-01-02',
    qty: '2'
  },
  {
    category: 'b',
    date: '2021-01-02',
    qty: '1'
  },
  {
    category: 'b',
    date: '2021-01-03',
    qty: '2'
  },
  {
    category: 'c',
    date: '2021-01-03',
    qty: '1'
  },
  {
    category: 'c',
    date: '2021-01-04',
    qty: '2'
  },
];
var output = [];
data.forEach(function(item) {
  var existing = output.filter(function(v, i) {
    return v.label == item.category;
  });
  if (existing.length) {
    var existingIndex = output.indexOf(existing[0]);
    output[existingIndex].datasets = output[existingIndex].datasets.concat(item.qty);
  } else {
    if (typeof item.qty == 'string') item.qty = [item.qty];
    output.push({
      label: item.category,
      datasets: item.qty
    });
  }
});
console.log('Output', output);

Answer

It looks like, you do not respect the lenth of the dat array and just push the value to the datasets of the group.

To overcome this, you could take an object for getting the index of the date and for not given datasets, map date with value zero.

const
    dates = ['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'],
    data = [{ category: 'a', date: '2021-01-01', qty: '1' }, { category: 'a', date: '2021-01-02', qty: '2' }, { category: 'b', date: '2021-01-02', qty: '1' }, { category: 'b', date: '2021-01-03', qty: '2' }, { category: 'c', date: '2021-01-03', qty: '1' }, { category: 'c', date: '2021-01-04', qty: '2' }],
    indices = Object.fromEntries(dates.map((k, i) => [k, i])),
    result = Object.values(data.reduce((groups, { category: label, date, qty }) => {
        groups[label] ??= { label, datasets: Array.from(dates).fill('0') };
        groups[label].datasets[indices[date]] = qty;
        return groups;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }