Create an object by flattening an array in his properties

John :

I need to create an array of objects where each single object contains only one value of the property array.

I will write an example of the input and expected result as I believe the question is quite confusing, but I don't really know how to explain it.

The first element of the array contains all the properties and only the first value of the array. Each one after the first one should have a unique id and a new property (ex. link) referring to the id of the first element.

INPUT:

const series = [
{
   id: 1,
   name: 'game of thrones',
   ep: ['01-01-2020','04-03-2020'] // This is the array that will split
},
{
   id: 2,
   name: 'stranger things',
   ep: ['03-02-2020']
}
]

EXPECTED OUTPUT:

const newSeries = [
{
   id: 1, // same id as before
   name: 'game of thrones', // same name as before
   ep: ['01-01-2020'] // first element of the previous array
},
{
   id: 2, // untouched
   name: 'stranger things',
   ep: ['03-02-2020']
},
{
   id: 35, // Any id
   ep: ['04-03-2020'] // second element
   link: 1 // This is the id of the original element
   // name is not necessary
}
// If ep had 3 dates, it would make a new element 
]

I do not mind about the order of the object. If there were any more elements in the array it would continue till is only a single one.

EDIT: Forgot to submit my attempt:

series.forEach(x => x.ep.map(epdate=> 
         newarray = [...newarray, {id:'some id', ep: epdate, link: x.id}]
    ))

I manage to split the array but I miss the logic to recognise if the item is the first and need to keep the name or if is after the first and need to have a link. Plus i need to create a random id which has to be unique.

Managed to had it working with this code:

serie.forEach(x => {
    x.ep.length > 1 ? 
    x.ep.map(y => 
        y === x.ep[0] ? 
         newarray = [...newarray, {id: x.id, name: x.name, ep: y}] :
        newarray = [...newarray, {id: 'id', ep: y, link: x.id}])
     : 
    newarray = [...newarray, {...x, ep: x.ep[0]}]
})

Only issue would be the id not being unique. I also recommend to check out Calvin's answer as it's extremely clear and clean code-wise.

Calvin Nunes :

There's more than one approach, but I always like to use good old fashioned for loops instead of ES6 syntaxes (in my opinion, for better readability), but let's see:

Use a for to loop your series array, check its ep to see if length is bigger than 1.
If yes, then you can do these steps:

  1. Get ep array into a new variable
  2. Push the serie object to the resulting array (newSeries)
  3. Use another for to loop the ep array (starting at index 1, since index 0 will stay in the original serie)
  4. Inside this loop, create a new object and set the properties you want
  5. Push this new object into newSeries

If no, then just push that serie object to newSeries.

const series = [
  { id: 1, name: 'game of thrones', ep: ['01-01-2020', '04-03-2020', '01-05-2020']},
  { id: 2, name: 'stranger things', ep: ['03-02-2020']}
]

let newSeries = [];
let idCounter = series.length + 1;

for (let i = 0; i < series.length; i++) {
  let serie = series[i]

  if (serie.ep.length > 1) {
    let allEps = serie.ep;
    serie.ep = [serie.ep[0]]
    newSeries.push(serie);

    for (let j = 1; j < allEps.length; j++) {
      let newSerieObj = {};
      newSerieObj.id = idCounter;
      newSerieObj.ep = [allEps[j]]
      newSerieObj.link = serie.id;
      newSeries.push(newSerieObj);
      idCounter++;
    }
  } 
  else {
    newSeries.push(serie)
  }
}

console.log(newSeries)
.as-console-wrapper {
  min-height: 100%
}

Note: I'm using a variable idCounter just for example purpose, You can use your own logic to set new Ids.

If you want the created objects (those with new id) to always come last in the array, you have two options: .sort by id; or don't push to newSeries but to another array, and just .concat this other array after all loops ended.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=29841&siteId=1