0

I'm trying to add my loop data to an object.

subItem.allAvgObj = {};

for(var i = 0; i < subItem.implementations.length; i++) {

if (subItem.implementations[i].avg_score) {

        Object.assign(subItem.allAvgObj, {
          scoreAvg: subItem.implementations[i].avg_score,
          scorePonderation: subItem.implementations[i].ponderation,
        })

    }
}

Only, there is only the last object of my loop that is assigned.

{
 "scoreAvg": 8,
 "scorePonderation": 10
}

I tried with an array, and it works (but it's an array with a single value, but the loop works)

subItem.allAvgArray.push(subItem.implementations[i].avg_score);

Return :

[
  13.5,
  16,
  8
]

How can I make an object like this?

{
  "scoreAvg": 13.5,
  "scorePonderation": 20
},
{
  "scoreAvg": 16,
  "scorePonderation": 20
},
{
  "scoreAvg": 8,
  "scorePonderation": 10
}

Thank you

Jeremy
  • 1,756
  • 3
  • 21
  • 45

2 Answers2

4

An easier way to create an array of objects might be to use .filter() to remove those without an avg_score(), and then .map() to create the resulting object from each item.

let result = subItem.implementations
  .filter(i => i.avg_score)
  .map(i => ({
    scoreAvg: i.avg_score,
    scorePonderation: i.ponderation
  }));

const subItem = {
  implementations: [{
      avg_score: 15.7,
      ponderation: 20
    },
    {
      avg_score: 0,
      ponderation: 15
    }, {
      avg_score: 6.8,
      ponderation: 10
    }
  ]
}

let result = subItem.implementations
  .filter(i => i.avg_score)  //remove items without avg_score
  .map(i => ({               //turn the remaining items into objects
    scoreAvg: i.avg_score,
    scorePonderation: i.ponderation
  }));
  
console.log(result);

Or, reduce() for a one-pass solution.

let result = subItem.implementations
  .reduce((acc,i) => 
    i.avg_score 
      ? [...acc, {scoreAvg: i.avg_score, scorePonderation: i.ponderation}] 
      : acc
  ,[]);

const subItem = {
  implementations: [{
      avg_score: 15.7,
      ponderation: 20
    },
    {
      avg_score: 0,
      ponderation: 15
    }, {
      avg_score: 6.8,
      ponderation: 10
    }
  ]
}

let result = subItem.implementations
  .reduce((acc,i) => 
    i.avg_score  //if avg_score, add an object. else, do nothing.
      ? [...acc, {scoreAvg: i.avg_score, scorePonderation: i.ponderation}] 
      : acc
  ,[]);

console.log(result);

Note that the reduce() solution makes up in performance what it lacks in readability.

Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
  • `reduce` solution is much better solution than `map` + `filter` from the point of view of performance. – spaniard Jan 22 '19 at 15:40
  • You're right, though it really depends on the length of the array. If it isn't a large array, the performance difference would be negligible. In such a case, some people prefer `filter` + `map` for readability. All in all though I agree with you and have modified my answer to note this. – Tyler Roper Jan 22 '19 at 15:42
2

Object.assign is used to shallow merge objects, not to create an array of objects that seems to be what you want.

Try:

subItem.allAvgObj = [];

for(var i = 0; i < subItem.implementations.length; i++) {

if (subItem.implementations[i].avg_score) {

        subItem.allAvgObj.push({
          scoreAvg: subItem.implementations[i].avg_score,
          scorePonderation: subItem.implementations[i].ponderation,
        })

    }
}

the expected output should be:

[
    {
      "scoreAvg": 13.5,
      "scorePonderation": 20
    },
    {
      "scoreAvg": 16,
      "scorePonderation": 20
    },
    {
      "scoreAvg": 8,
      "scorePonderation": 10
    }
]
spaniard
  • 541
  • 2
  • 12