setting object key dynamically in javascript

Viewed 76

I have an object like this:

let inputData = {
  "dimensions": [
    {
      "id": "dimension_re",
      "label": "Region",
      "values": ["East", "East", "West", "SouthWest", "South","NorthEast"]
    }, 
    {
      "id": "dimension_cnt",
      "label": "County",
      "values": ["London", "Italy", "Germany", "US", "Russia","India"]
    },
    {
      "id": "measure_sales",
      "label": "Sales",
      "values": [100, 156, 432, 462, 25,100]
    }, 
    {
      "id": "measure_qty",
      "label": "Quantity",
      "values": [85, 34, 153, 434, 52, 43]
    }, 
    {
      "id": "measure_profit",
      "label": "Profit",
      "values": [123, 45, 421, 465, 451, 56]
    }
  ]
}

My expected output:

let expectdData = [
  {
    "Region": "East",
    "County": "London",
    "Sales": 100,
    "Quantity": 85,
    "Profit": 123
  }, 
  {
    "Region": "East",
    "County": "Italy",
    "Sales": 156,
    "Quantity": 34,
    "Profit": 45
  }, 
  {
    "Region": "West",
    "County": "Germany",
    "Sales": 432,
    "Quantity": 153,
    "Profit": 421
  }, 
  {
    "Region": "SouthWest",
    "County": "US",
    "Sales": 462,
    "Quantity": 434,
    "Profit": 465
  }, 
  {
    "Region": "South",
    "County": "Russia",
    "Sales": 25,
    "Quantity": 52,
    "Profit": 451
  },
  {
    "Region": "NorthEast",
    "County": "India",
    "Sales": 100,
    "Quantity": 43,
    "Profit": 56
  }
]

Here is my program to get this expected data:

let actualData = [];

inputData.dimensions.forEach((e,i) => {
  let tempVal = e.label;
  e.values.forEach((elem,index) => {
    actualData[index] = new Object({
      [tempVal] : elem
    });
  })
});

console.log(actualData);

But unfortunately, I only get the last item for every object. In my console it looks like this:

[
  { Profit: 123 },
  { Profit: 45 },
  { Profit: 421 },
  { Profit: 465 },
  { Profit: 451 },
  { Profit: 56 }
]

I think, in every iteration, it just overrides the "tempVal" variable. How to prevent this & how can I achieve the expected array of objects?

3 Answers

You are replacing the whole object on each iteration, you just need to create it if it does not exists, otherwise you can replace the key.

let actualData = [];

inputData.dimensions.forEach((e,i)=>{
  let tempVal = e.label;
  e.values.forEach((elem,index) => {
    if (!actualData[index]) {
      actualData[index] = {}
    }
    actualData[index][tempVal] = elem
  })
});

console.log(actualData);
  • Using Array#reduce, iterate over dimension while updating a list of the resulting objects
  • In each iteration, use Array#forEach to iterate over the current values list and update the object at each index with label as key and the current value as value

const inputData = {
  "dimensions": [
    {
      "id": "dimension_re",
      "label": "Region",
      "values": ["East", "East", "West", "SouthWest", "South","NorthEast"]
    }, 
    {
      "id": "dimension_cnt",
      "label": "County",
      "values": ["London", "Italy", "Germany", "US", "Russia","India"]
    },
    {
      "id": "measure_sales",
      "label": "Sales",
      "values": [100, 156, 432, 462, 25,100]
    }, 
    {
      "id": "measure_qty",
      "label": "Quantity",
      "values": [85, 34, 153, 434, 52, 43]
    }, 
    {
      "id": "measure_profit",
      "label": "Profit",
      "values": [123, 45, 421, 465, 451, 56]
    }
  ]
};

const res = inputData.dimensions.reduce((acc, { label, values = [] }) => {
  values.forEach((value, index) => {
    acc[index] = { ...(acc[index] ?? {}), [label]: value };
  });
  return acc;
}, []);

console.log(res);

Since your index comes from the inner loop, you'll be replacing the values at actualData[index] each outer loop iteration, that's why you only end up with the last.

Try this reduce operation instead...

const inputData = {"dimensions":[{"id":"dimension_re","label":"Region","values":["East","East","West","SouthWest","South","NorthEast"]},{"id":"dimension_cnt","label":"County","values":["London","Italy","Germany","US","Russia","India"]},{"id":"measure_sales","label":"Sales","values":[100,156,432,462,25,100]},{"id":"measure_qty","label":"Quantity","values":[85,34,153,434,52,43]},{"id":"measure_profit","label":"Profit","values":[123,45,421,465,451,56]}]};

// Find the max number of `values`
const maxLength = Math.max(...inputData.dimensions.map(({ values }) => values.length));

const actualData = inputData.dimensions.reduce(
  (arr, { label, values }) =>
    arr.map((obj, i) => ({ ...obj, [label]: values[i] })),
  Array.from(
    {
      length: maxLength,
    },
    () => ({}) // creates an array of empty objects
  )
);
  
console.log(actualData);
.as-console-wrapper { max-height: 100% !important; }

Related