Home > Net >  How to update object based off objects specific value?
How to update object based off objects specific value?

Time:11-11

I have 2 objects and I want to 'transplant' values from one object into the other.

The first object I am drawing data from looks like:

var userData = {
  Data: [
    {
      Amount: 430140.68,
      Year: "2015",
      AccountName: "Account 1"
    },
    {
      Amount: 458997.32,
      Year: "2016",
      Name: "Account 2"
    },
  ]
}

The 2nd object I am placing data into looks like:

[
    {
        "name": "Account 1",
        "data": [
            0,
            0
        ],
    },
    {
        "name": "Account 2",
        "data": [
            0,
            0
        ],
    }
]

My goal is to take the Amount form the first object and place it in the data array of the 2nd. Each year corresponds to a value in the 'data` array.

So, the resulting updated object should look like:

[
    {
        "name": "Account 1",
        "data": [
            430140.68,
            0
        ],
    },
    {
        "name": "Account 2",
        "data": [
            0,
            458997.32
        ],
    }
]

To try to achieve this I have the following code:

const yearArrLength = yearsArr.length;
const generatedObj = new Array(yearArrLength).fill(0);
// Push name and populate data array with 0s.
for (var key of Object.keys(userData.Data)) {
    var accName = userData.Data[key].AccountName;
    if (!generatedObj.find(key => key.name === accName)){
        generatedObj.push({'name': accName, 'data': blankDataArr});
    }
}

for (var key of Object.keys(userData.Data)) {
    var accName = userData.Data[key].AccountName;
    var accAmount = userData.Data[key].Amount;
    var accYear = userData.Data[key].Year;

    // Get location of years array value
    var yearArrIndex = yearsArr.indexOf(accYear);

    for (var key of Object.keys(generatedObj)) {
        if (generatedObj[key].name == accName) {
            generatedObj[key].data[yearArrIndex] = accAmount;
        }
    }

}

However, this seems to populate all of the data array values, eg:

[
    {
        "name": "Account 1",
        "data": [
            430140.68,
            458997.32
        ],
    },
    {
        "name": "Account 2",
        "data": [
            430140.68,
            458997.32
        ],
    }
]

I'm completely stumped as to why. The if statement should be checking if there is a matching account name, but it doesn't seem to fire.

Would anyone know what I've done wrong?

CodePudding user response:

It looks like you're pushing the exact same blankDataArr each time - you're not pushing a new array, you're pushing the same array to all.

For a more minimal example:

const subarr = [];

const arr = [subarr, subarr];
arr[0].push('x');
console.log(JSON.stringify(arr));

// both items in `arr` have changed
// because both refer to the exact same subarr object
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

For what you're trying to do, it looks like it'd be a lot easier to make an object or Map indexed by AccountName first, that way you just have to access or create the AccountName property while iterating, and assign to the appropriate year.

const yearsArr = ['2015', '2016'];
const userData = {
  Data: [
    {
      Amount: 430140.68,
      Year: "2015",
      AccountName: "Account 1"
    },
    {
      Amount: 458997.32,
      Year: "2016",
      AccountName: "Account 2"
    },
  ]
};

const dataByAccountName = new Map();
for (const { AccountName, Amount, Year } of userData.Data) {
  if (!dataByAccountName.has(AccountName)) {
    // Create an entirely new array:
    dataByAccountName.set(AccountName, yearsArr.map(() => 0));
  }
  const index = yearsArr.indexOf(Year);
  dataByAccountName.get(AccountName)[index] = Amount;
}
const result = [...dataByAccountName.entries()].map(([name, data]) => ({ name, data }));
console.log(result);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related