Search code examples
javascripthighchartsjavascript-objects

Transform array of objects into a transposed array of objects


I need to transform an array of objects into another array of objects but transposed. This is the form highcharts accepts arrays.

I need to go from

    var n0 = [{
        "a": 1,
        "b": 4
    }, {
        "a": 2,
        "b": 6
    }, {
        "a": 3,
        "b": 8
    }]

to

    var n1 = [{
        "name": "a",
        "data": [1, 2, 3]
    }, {
        "name": "b",
        "data": [4, 6, 8]
    }];

What about changing from

            var input = [{
                "date": "JAN",
                "category": "abc",
                "thevalue": 5
            }, {
                "date": "JAN",
                "category": "xyz",
                "thevalue": 4
            }, {
                "date": "FEB",
                "category": "abc",
                "thevalue": 9
            }, {
                "date": "FEB",
                "category": "xyz",
                "thevalue": 10
            }]

To

                var output = [{
                    "name": "abc",
                    "data": [5,9]
                }, {
                    "name": "xyz",
                    "data": [4, 10]
                }];

Can this be accomplished with the same functions? I've read two javascript books but somehow these puzzles are far above my abilities. I don't even know where to start learning. I guess I could reread the chapter about objects and arrays, the issue is those examples are very basic.


Solution

  • An easy way to solve this is to keep in mind that every key you're using exists in each entry of the input array. Getting an array all of the keys of any of those objects using Object.keys gives you the list of names. From there, iterate over that array and keep selecting out the specific key value you're interested in using .map.

    Just a heads up, this will throw an error if your array is empty. You can have an early return condition if you encounter that corner case.

    If you have any questions about the syntax I use, feel free to ask for clarification.

        var n0 = [{
          "a": 1,
          "b": 4,
          "c": 5
        }, {
          "a": 2,
          "b": 6,
          "c": 4
        }, {
          "a": 3,
          "b": 8,
          "c": 10
        }]
    
        function transposeObject(array) {
          const newArr = [] // an empty array I make to store my values that I will eventually return
          const arrayOfKeys = Object.keys(array[0]) // selecting the first element in the array. Taking the keys as an array
          arrayKeys.forEach(name => {
            const newObj = { name }; // new object. I insert the name to start.
            const arrayOfNumbersByKeyName = array.map(object => object[name]) // create new array that is only compromised of the value from object[name], where name is a variable representing a key from arrayKeys
            newObj.data = arrayOfNumbersByKeyName // insert my newly created array into newObject under the key 'data'
            newArr.push(newObj) // push my fully constructed array into my newArr that I initialized at the top of the function
          });
          return newArr
        }
    
        console.log(transposeObject(n0))

    Update:

    It looks like you're trying to get every value that correlates with a key from category. Apologies, but there's no "easy" way to solve this unless you want to write an incredibly long algorithm.

    One way is to grab every possible value of key and then filtering only for the specific category name each time.

    var input = [{
        "date": "JAN",
        "category": "abc",
        "thevalue": 5
    }, {
        "date": "JAN",
        "category": "xyz",
        "thevalue": 4
    }, {
        "date": "FEB",
        "category": "abc",
        "thevalue": 9
    }, {
        "date": "FEB",
        "category": "xyz",
        "thevalue": 10
    }]
    
    function generateGraphData(array) {
        const newArr = []
        const arrayOfCategories = array.map(object => object.category)
        const setOfCategories = new Set(arrayOfCategories)
        for (const category of setOfCategories) {
            const filteredCategories = array.filter(obj => obj.category === category)
            const graphData = filteredCategories.map(obj => obj.thevalue)
            newArr.push({ name: category, data: graphData})
        }
        return newArr
    }
    
    const data = generateGraphData(input)
    console.log(data)