0

I want be able to convert below array or objects with uniform keys, but have it pivoted or transformed into array of objects, but with as many objects as there are properties in an object, with each object now having the name of property along with keys for each value for a specified key in the original (in this case all the possible vales of they "year" from original array). And I also want to get this array re-transposed into original form.

I want to know if this is possible to do in a generic way so it can be done with any type of object and based on any of its key's values.

Input:

[
    {
        "property0": "property0_2024",
        "property1": "property1_2024",
        "property2": "property2_2024",
        "property3": "property3_2024",
        "property4": "property4_2024",
        "year": "2024"
    },
    {
        "property0": "property0_2025",
        "property1": "property1_2025",
        "property2": "property2_2025",
        "property3": "property3_2025",
        "property4": "property4_2025",
        "year": "2025"
    },
    {
        "property0": "property0_2026",
        "property1": "property1_2026",
        "property2": "property2_2026",
        "property3": "property3_2026",
        "property4": "property4_2026",
        "year": "2026"
    },
    {
        "property0": "property0_2027",
        "property1": "property1_2027",
        "property2": "property2_2027",
        "property3": "property3_2027",
        "property4": "property4_2027",
        "year": "2027"
    }
]

Output:

[
    {
        "propertyName": "property0",
        "year_2024": "property0_2024",
        "year_2025": "property0_2025",
        "year_2026": "property0_2026",
        "year_2027": "property0_2027"
    },
    {
        "propertyName": "property1",
        "year_2024": "property1_2024",
        "year_2025": "property1_2025",
        "year_2026": "property1_2026",
        "year_2027": "property1_2027"
    },
    {
        "propertyName": "property2",
        "year_2024": "property2_2024",
        "year_2025": "property2_2025",
        "year_2026": "property2_2026",
        "year_2027": "property2_2027"
    },
    {
        "propertyName": "property3",
        "year_2024": "property3_2024",
        "year_2025": "property3_2025",
        "year_2026": "property3_2026",
        "year_2027": "property3_2027"
    },
    {
        "propertyName": "property4",
        "year_2024": "property4_2024",
        "year_2025": "property4_2025",
        "year_2026": "property4_2026",
        "year_2027": "property4_2027"
    }
]
0

2 Answers 2

1

You can pivot your data around a specified key.

Use a Set to uniquely store your properties, filtering out duplicates.

Then, it’s just a matter of generating a new array in which each entry is a new object with values taken from the input array.

Here’s an example:

function pivotData(inputArray, pivotKey, propertyKeyName = "propertyName") {
  // Consider only unique properties and exclude the pivotKey
  const properties = new Set();
  const pivotValues = [];

  inputArray.forEach((item) => {
    Object.keys(item).forEach((key) => {
      if (key !== pivotKey) {
        properties.add(key);
      }
    });
    pivotValues.push(item[pivotKey]);
  });

  const result = [];
  properties.forEach((property) => {
    const obj = {};
    obj[propertyKeyName] = property;
    inputArray.forEach((item) => {
      const pivotValue = item[pivotKey];
      const key = `${pivotKey}_${pivotValue}`;
      obj[key] = item[property];
    });
    result.push(obj);
  });

  return result;
}

function reversePivotData(
  pivotedArray,
  pivotKey,
  propertyKeyName = "propertyName"
) {
  const result = [];
  const pivotValuesSet = new Set();

  // Collect all pivot values from the keys in the pivoted array
  pivotedArray.forEach((item) => {
    Object.keys(item).forEach((key) => {
      if (key !== propertyKeyName) {
        const [keyPrefix, ...pivotValueParts] = key.split("_");
        if (keyPrefix === pivotKey) {
          const pivotValue = pivotValueParts.join("_");
          pivotValuesSet.add(pivotValue);
        }
      }
    });
  });

  const pivotValues = Array.from(pivotValuesSet);

  // Initialize an object for each pivot value
  pivotValues.forEach((pivotValue) => {
    const obj = {};
    obj[pivotKey] = pivotValue;

    pivotedArray.forEach((item) => {
      const propertyName = item[propertyKeyName];
      const key = `${pivotKey}_${pivotValue}`;
      if (item.hasOwnProperty(key)) {
        obj[propertyName] = item[key];
      }
    });

    result.push(obj);
  });

  return result;
}

// Example usage:
const inputData = [
  {
    property0: "property0_2024",
    property1: "property1_2024",
    property2: "property2_2024",
    property3: "property3_2024",
    property4: "property4_2024",
    year: "2024",
  },
  {
    property0: "property0_2025",
    property1: "property1_2025",
    property2: "property2_2025",
    property3: "property3_2025",
    property4: "property4_2025",
    year: "2025",
  },
  {
    property0: "property0_2026",
    property1: "property1_2026",
    property2: "property2_2026",
    property3: "property3_2026",
    property4: "property4_2026",
    year: "2026",
  },
  {
    property0: "property0_2027",
    property1: "property1_2027",
    property2: "property2_2027",
    property3: "property3_2027",
    property4: "property4_2027",
    year: "2027",
  },
];

const pivotedData = pivotData(inputData, "year");
console.log("Pivoted Data:", pivotedData);

const reversedData = reversePivotData(pivotedData, "year");
console.log("Reversed Data:", reversedData);

 

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot, I'm working on a way to take the result and reverse it to get the original array of objects, how can we do it?. I have taken first all the property names of properties in a set and now I'm taking the value of a year from each object of the result.
yes that worked for me. thanks.!
1

Reduce the array to a Map by propertyName. Iterate each objects entries, and use the key of each property to locate the object inside the map, and add the property's value by the year. Convert the map to an array with Array.from():

const fn = arr => Array.from(arr.reduce((acc, { year, ...props }) => {
  const yearKey = `year_${year}`
  
  Object.entries(props).forEach(([key, val]) => {
    if(!acc.has(key)) acc.set(key, { propertyName: key })
    
    acc.get(key)[yearKey] = val
  })
  
  return acc
}, new Map()).values())

const arr = [{"property0":"property0_2024","property1":"property1_2024","property2":"property2_2024","property3":"property3_2024","property4":"property4_2024","year":"2024"},{"property0":"property0_2025","property1":"property1_2025","property2":"property2_2025","property3":"property3_2025","property4":"property4_2025","year":"2025"},{"property0":"property0_2026","property1":"property1_2026","property2":"property2_2026","property3":"property3_2026","property4":"property4_2026","year":"2026"},{"property0":"property0_2027","property1":"property1_2027","property2":"property2_2027","property3":"property3_2027","property4":"property4_2027","year":"2027"}]

const result = fn(arr)

console.log(result)

1 Comment

Thanks a lot, I'm working on a way to take the result and reverse it to get the original array of objects, how can we do it?. I have taken first all the property names of properties in a set and now Im taking the value of a year from each object of the result.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.