#javascript #jquery
Вопрос:
У меня есть 2 объекта, и я хочу «пересадить» значения из одного объекта в другой.
Первый объект, из которого я черпаю данные, выглядит так:
var userData = { Data: [ { Amount: 430140.68, Year: "2015", AccountName: "Account 1" }, { Amount: 458997.32, Year: "2016", Name: "Account 2" }, ] }
2-й объект, в который я помещаю данные, выглядит так:
[ { "name": "Account 1", "data": [ 0, 0 ], }, { "name": "Account 2", "data": [ 0, 0 ], } ]
Моя цель состоит в том, чтобы принять Amount
форму первого объекта и поместить его в data
массив 2-го. Каждый год соответствует значению в массиве «данные».
Таким образом, полученный обновленный объект должен выглядеть следующим образом:
[ { "name": "Account 1", "data": [ 430140.68, 0 ], }, { "name": "Account 2", "data": [ 0, 458997.32 ], } ]
Чтобы попытаться достичь этого, у меня есть следующий код:
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 =gt; 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 ], } ]
Я совершенно не понимаю, почему. В if
заявлении следует проверить, есть ли совпадающее имя учетной записи, но, похоже, оно не срабатывает.
Кто-нибудь знает, что я сделал не так?
Ответ №1:
Похоже blankDataArr
, что вы каждый раз нажимаете одно и то же — вы не нажимаете новый массив, вы нажимаете один и тот же массив для всех.
Для более минимального примера:
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
Для того, что вы пытаетесь сделать, похоже, что было бы намного проще сначала индексировать объект или карту AccountName
, таким образом, вам просто нужно получить доступ или создать AccountName
свойство во время итерации и назначить соответствующий год.
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(() =gt; 0)); } const index = yearsArr.indexOf(Year); dataByAccountName.get(AccountName)[index] = Amount; } const result = [...dataByAccountName.entries()].map(([name, data]) =gt; ({ name, data })); console.log(result);
Комментарии:
1. Большое спасибо! Извините, я совсем не силен в ES6. Как бы я добавил больше (статических) данных в новый объект? Например: Мне нужно добавить
"type": "bar"
к каждому. Я попробовал несколько способов, но не смог понять этого.2. Не могу сказать наверняка, не зная точно, какого рода данные, но, возможно, вам просто нужно добавить свойство или несколько к объекту, возвращенному в финале
.map
?({ name, data })
к({ name, data, someOtherProp })
или({ name, data, type: 'bar' })