Дядя Фея
Дядя Фея

Reputation: 359

Make N copies of JS object and make changes in it

I have an array of objects like this:

[
  {
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
]

I need to do a complex of modifications:

1) Create a new array with N copies of start array, for example 2:

[
  {
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
  {
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
]

2) Set the index for each object in the field field

[
  {
    headerName: 'Make',
    field: 'make0',
  },
  {
    headerName: 'Model',
    field: 'model0',
  },
  {
    headerName: 'Price',
    field: 'price0',
  },
  {
    headerName: 'Make',
    field: 'make1',
  },
  {
    headerName: 'Model',
    field: 'model1',
  },
  {
    headerName: 'Price',
    field: 'price1',
  }
]

How to implement this function?

PS. I have own option of this function, but it is not working correctly:

export const formatColumns = (columns, pageCount) => {
  let formatArray = []

  for (let i = 0; i < pageCount; i++) {
    let copy = columns.slice(0)

    formatArray = [...formatArray, ...copy.map(item => (item.field = item.field + i))]
  }
  console.log(formatArray)
}

const columns = [
  {
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
  {
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
]

const formatColumns = (columns, pageCount) => {
  let formatArray = []

  for (let i = 0; i < pageCount; i++) {
    let copy = columns.slice(0)

    formatArray = [...formatArray, ...copy.map(item => (item.field = item.field + i))]
  }
  console.log(formatArray)
}

formatColumns(columns, 2);

The result of this function is:

0: "make0"
1: "model0"
2: "price0"
3: "make01"
4: "model01"
5: "price01"
6: "make012"
7: "model012"
8: "price012"
9: "make0123"
10: "model0123"
11: "price0123"
12: "make01234"
13: "model01234"
14: "price01234"
15: "make012345"
16: "model012345"
17: "price012345"

What am I doing wrong, and how should I fix it?

Upvotes: 1

Views: 416

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370769

When creating additional copies of the objects with Array.from, take the current index in the mapper function, and append it to the field value of every object:

const copies = 3;

const arr = [{
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
];

const output = Array.from(
  { length: copies },
  (_, i) => arr.map(
    ({ field, ...rest }) => ({ ...rest, field: field + i })
  )
)
  .flat()
console.log(output);

Or, if you want to stick with your for loop:

const copies = 3;

const arr = [{
    headerName: 'Make',
    field: 'make',
  },
  {
    headerName: 'Model',
    field: 'model',
  },
  {
    headerName: 'Price',
    field: 'price',
  },
];

let output = [];

for (let i = 0; i < copies; i++) {
  const copy = arr.slice().map(({ field, ...rest }) => ({ ...rest, field: field + i }));
  output = [...output, ...copy]
}
console.log(output);

A problem with your original code is that when you do

let copy = columns.slice(0)
...copy.map(item => (item.field = item.field + i))

you're not copying the objects - .slice only creates a shallow copy of the array, and then inside the .map, you mutate the existing objects, without copying them (and then you return the result of the item.field + i expression, which isn't desirable).

You need to fully copy the object inside the .map callback instead, and return a new object with an altered field.

Upvotes: 6

Related Questions