Harsh T
Harsh T

Reputation: 21

Create Javascript Array Object

I am having an object as below

[
  {
    assetName: "equity",
    colorCode: "#7C80A2",
    values: [
      { year: "2025", assetValue: 10 },
      { year: "2030", assetValue: 10 },
      { year: "2035", assetValue: 0 },
      { year: "2040", assetValue: 0 },
      { year: "2045", assetValue: 0 },
      { year: "2050", assetValue: 0 },
      { year: "2055", assetValue: 0 },
      { year: "2060", assetValue: 0 }
    ]
  },
  {
    assetName: "fixedIncome",
    colorCode: "#C39936",
    values: [
      { year: "2025", assetValue: 10 },
      { year: "2030", assetValue: 14 },
      { year: "2035", assetValue: 11 },
      { year: "2040", assetValue: 10 },
      { year: "2045", assetValue: 8 },
      { year: "2050", assetValue: 1 },
      { year: "2055", assetValue: 0 },
      { year: "2060", assetValue: 0 }
    ]
  },
  {
    assetName: "opportunistics",
    colorCode: "#5E6873",
    values: [
      { year: "2025", assetValue: 18 },
      { year: "2030", assetValue: 16 },
      { year: "2035", assetValue: 17 },
      { year: "2040", assetValue: 10 },
      { year: "2045", assetValue: 12 },
      { year: "2050", assetValue: 7 },
      { year: "2055", assetValue: 3 },
      { year: "2060", assetValue: 0 }
    ]
  },
  {
    assetName: "assets",
    colorCode: "#5E8987",
    values: [
      { year: "2025", assetValue: 14 },
      { year: "2030", assetValue: 14 },
      { year: "2035", assetValue: 8 },
      { year: "2040", assetValue: 14 },
      { year: "2045", assetValue: 13 },
      { year: "2050", assetValue: 10 },
      { year: "2055", assetValue: 5 },
      { year: "2060", assetValue: 0 }
    ]
  }
];

I want output as below

[
  { year: 2025, equity: 10, fixedIncome: 10, opportunistics: 18, assets: 14 },
  { year: 2030, equity: 10, fixedIncome: 14, opportunistics: 16, assets: 14 },
  { year: 2035, equity: 0, fixedIncome: 11, opportunistics: 17, assets: 8 },
  { year: 2040, equity: 0, fixedIncome: 10, opportunistics: 10, assets: 14 },
  { year: 2045, equity: 0, fixedIncome: 8, opportunistics: 12, assets: 13 },
  { year: 2050, equity: 0, fixedIncome: 1, opportunistics: 7, assets: 10 },
  { year: 2055, equity: 0, fixedIncome: 0, opportunistics: 3, assets: 5 },
  { year: 2060, equity: 0, fixedIncome: 0, opportunistics: 0, assets: 0 }
];

I am trying below code, but not able to get the expected result

function transformData(data) {
  let newData = [];
  for (let i = 0; i < data.length; i++) {
    // data length is 4
    assetNameString = data[i].assetName;
    values = data[i].values;
    for (let j = 0; j < values.length; j++) {
      // values lenght is 8
      newData.push({
        year: values[j].year,
        assetValue: values[j].assetValue
      });
    }
  }
  console.log(newData);
}
transformData(data);

Any help is highly appreciated.

Upvotes: 2

Views: 46

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074138

You've got the right idea, but you need to track the years so you can add to them as you encounter assets. See comments:

function transformData(data) {
    // Use a map to get by-year information
    let yearData = new Map();
    // Loop through the data, using destructuring to get the info we want
    for (const {assetName, values} of data) {
        // Loop through the values array, destructuring again
        for (const {year, assetValue} of values) {
            // Get or add the year entry
            const yearEntry = yearData.get(year) || {year};
            yearData.set(year, yearEntry);
            // Add the asset
            yearEntry[assetName] = assetValue;
        }
    }
    // Get an array of the values
    const newData = [...yearData.values()];
    console.log(newData);
}

Live Example:

const data = [
        { assetName: 'equity', colorCode: '#7C80A2', values: [{ year: "2025", assetValue: 10 }, { year: "2030", assetValue: 10 }, { year: "2035", assetValue: 0 }, { year: "2040", assetValue: 0 }, { year: "2045", assetValue: 0 }, { year: "2050", assetValue: 0 }, { year: "2055", assetValue: 0 }, { year: "2060", assetValue: 0 }] },
        { assetName: 'fixedIncome', colorCode: '#C39936', values: [{ year: "2025", assetValue: 10 }, { year: "2030", assetValue: 14 }, { year: "2035", assetValue: 11 }, { year: "2040", assetValue: 10 }, { year: "2045", assetValue: 8 }, { year: "2050", assetValue: 1 }, { year: "2055", assetValue: 0 }, { year: "2060", assetValue: 0 }] },
        { assetName: 'opportunistics', colorCode: '#5E6873', values: [{ year: "2025", assetValue: 18 }, { year: "2030", assetValue: 16 }, { year: "2035", assetValue: 17 }, { year: "2040", assetValue: 10 }, { year: "2045", assetValue: 12 }, { year: "2050", assetValue: 7 }, { year: "2055", assetValue: 3 }, { year: "2060", assetValue: 0 }] },
        { assetName: 'assets', colorCode: '#5E8987', values: [{ year: "2025", assetValue: 14 }, { year: "2030", assetValue: 14 }, { year: "2035", assetValue: 8 }, { year: "2040", assetValue: 14 }, { year: "2045", assetValue: 13 }, { year: "2050", assetValue: 10 }, { year: "2055", assetValue: 5 }, { year: "2060", assetValue: 0 }] }];

function transformData(data) {
    // Use a map to get by-year information
    let yearData = new Map();
    // Loop through the data, using destructuring to get the info we want
    for (const {assetName, values} of data) {
        // Loop through the values array, destructuring again
        for (const {year, assetValue} of values) {
            // Get or add the year entry
            const yearEntry = yearData.get(year) || {year};
            yearData.set(year, yearEntry);
            // Add the asset
            yearEntry[assetName] = assetValue;
        }
    }
    // Get an array of the values
    const newData = [...yearData.values()];
    console.log(newData);
}

transformData(data);
.as-console-wrapper {
    max-height: 100% !important;
}

Technically, this calls set unnecessarily a lot:

// Get or add the year entry
const yearEntry = yearData.get(year) || {year};
yearData.set(year, yearEntry);

You could do this instead to avoid that if you prefer:

// Get or add the year entry
let yearEntry = yearData.get(year);
if (!yearEntry) {
    yearEntry = {year};
    yearData.set(year, yearEntry);
}

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386550

You could group with an object and collect all values.

var data = [{ assetName: 'equity', colorCode: '#7C80A2', values: [{ year: "2025", assetValue: 10 }, { year: "2030", assetValue: 10 }, { year: "2035", assetValue: 0 }, { year: "2040", assetValue: 0 }, { year: "2045", assetValue: 0 }, { year: "2050", assetValue: 0 }, { year: "2055", assetValue: 0 }, { year: "2060", assetValue: 0 }] }, { assetName: 'fixedIncome', colorCode: '#C39936', values: [{ year: "2025", assetValue: 10 }, { year: "2030", assetValue: 14 }, { year: "2035", assetValue: 11 }, { year: "2040", assetValue: 10 }, { year: "2045", assetValue: 8 }, { year: "2050", assetValue: 1 }, { year: "2055", assetValue: 0 }, { year: "2060", assetValue: 0 }] }, { assetName: 'opportunistics', colorCode: '#5E6873', values: [{ year: "2025", assetValue: 18 }, { year: "2030", assetValue: 16 }, { year: "2035", assetValue: 17 }, { year: "2040", assetValue: 10 }, { year: "2045", assetValue: 12 }, { year: "2050", assetValue: 7 }, { year: "2055", assetValue: 3 }, { year: "2060", assetValue: 0 }] }, { assetName: 'assets', colorCode: '#5E8987', values: [{ year: "2025", assetValue: 14 }, { year: "2030", assetValue: 14 }, { year: "2035", assetValue: 8 }, { year: "2040", assetValue: 14 }, { year: "2045", assetValue: 13 }, { year: "2050", assetValue: 10 }, { year: "2055", assetValue: 5 }, { year: "2060", assetValue: 0 }] }],
    result = Object.values(data.reduce((r, { assetName, values }) => {
        values.forEach(({ year, assetValue }) => 
            (r[year] = r[year] || { year })[assetName] = assetValue
        );
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Related Questions