Fixed size 2d array of objects My Objective is to create a fixed column array object of size 4 columns so that I can form a 2d array in the following format which I can use to print to a pdf later. The solution is working fine.
But need help in figuring out if there is a better way to implement this.

let input = [{
  id:123,
  quantity: 4,
  value: "xxxx"
},
{
  id:234,
  quantity: 11,
  value: "xxxx"
},
{
  id:345,
  quantity: 1,
  value: "xxxx"
}]


output = [
    [ objHeader, objValue, objValue, objValue ],
    [ objValue, null, null, null ],
    [ objHeader1, objValue1, objValue1, objValue1 ],
    [ objValue1, objValue1, objValue1, objValue1 ],
    [ objValue1, objValue1, objValue1, objValue1 ],
    [ objHeader2, objValue2, null, null ]
]

where objHeader = {
    id:123,
    header:true,
    quantity: 4,
    value: xxxx
}
objValue = {
    id:123,
    header:false,
    quantity: 4,
    value: xxxx
}


objValue is basically input[0].id repeated by the factor present in quantity

objValue1 is input[1].id repeated by the factor present in quantity and so on

Code that is working now



let input = [
  {
    id: 123,
    quantity: 4,
    value: "x1xxx"
  },
  {
    id: 234,
    quantity: 11,
    value: "x2xxx"
  },
  {
    id: 345,
    quantity: 1,
    value: "x3xxx"
  }
];

class RowRecord {
  constructor(rowsize = 4) {
    this.items = Array(rowsize).fill(null);
    this.rowSize = rowsize;
  }

  push(item) {
    const currentSize = this.size();
    // console.log(currentSize);
    if (currentSize &lt; this.rowSize) {
      // replace 1 items with null based on index
      this.items.splice(currentSize, 1, item);
    }
  }

  get() {
    return this.items;
  }

  size() {
    return this.items.filter(item =&gt; item !== null).length;
  }
}

function getRecords() {
  const records = [];
  let rows = new RowRecord(); // fill default
  // create records
  for (let i = 0; i &lt; input.length; i++) {
    // check for pending rows
    if (i !== 0 &amp;&amp; rows.size() &gt; 0) {
      records.push(rows);
    }
    // initiate new row
    rows = new RowRecord();
    const item = input[i];
    const quantity = parseInt(item.quantity, 10);
    const value = item.value;
    // +1 for printing the label for each product
    for (let j = 0; j &lt;= quantity; j++) {
      if (j === 0) {
        // title label
        rows.push({
          id: item.id,
          header: true,
          quantity,
          value
        });
      } else {
        if (rows.size() === 4) {
          records.push(rows);
          rows = new RowRecord();
        }
        rows.push({
          id: item.id,
          header: false,
          quantity,
          value
        });
      }
    }
  }
  // push any pending rows
  records.push(rows);
  return records;
}

console.log(getRecords());
You can also use Array.prototype.reduce to generate the fixed size 2d array.


const input = [{
  id: 123, quantity: 4, value: "x1xxx"
}, {
  id: 234, quantity: 11, value: "x2xxx"
}, {
  id: 345, quantity: 1, value: "x3xxx"
}];

function getNewRecords(rowSize = 4) {
  return input.reduce((records, current) =&gt; {
    let items = [];
    Array.from({
      length: current.quantity + 1 // +1 for header column
    }).forEach((_, index) =&gt; {
      const record = {
        header: index === 0,
        id: current.id,
        quantity: current.quantity,
        value: current.value
      }

      if (items.length === rowSize) {
        records.push({ items, rowSize });

        items = [];
      }

      items.push(record);
    });

    if (items.length &lt; rowSize) {
      items.push(...Array(rowSize - items.length).fill(null));
    }

    records.push({ items, rowSize });

    return records;

  }, []);
}

console.log(getNewRecords());