Search code examples
javascriptarraysecmascript-6javascript-objects

How to build new object using keys from array of keys and values from another array of objects


I have this array of keys:

["newId", "newFirstName", "newLastName"]

and i have also array of objects that looks like this:

[{"oldId":1, "oldFirstName":"name1", "oldLastName":"lastName1", ...not impotent data }, { "oldId":2, "oldFirstName":"name2", "oldLastName":"lastName2", ...not impotent data }]

I want result of this array:

[{"newId":1, "newFirstName":"name1", "newLastName":"lastName1", }, { "newId":2, "newFirstName":"name2", "newLastName":"lastName2", }]


Solution

  • If you can be sure that the order of old keys in your object will never change and there will never be a key missing, then you can do something like this:

    const newKeys = ['newId', 'newFirstName', 'newLastName']
    
    const transform = obj => Object.fromEntries(
      Object.entries(obj)
        .slice(0, newKeys.length)
        .map(([key, value], index) => [newKeys[index], value])
    )
    
    const oldArray = [
      {
        oldId: 1,
        oldFirstName: 'A',
        oldLastName: 'B',
        unimportant: 'x'
      },
      {
        oldId: 2,
        oldFirstName: 'C',
        oldLastName: 'D',
        unimportant: 'x'
      }
    ]
    
    const newArray = oldArray.map(transform)
    
    console.log(newArray)
    /* Result:
    [
      {
        newId: 1,
        newFirstName: 'A',
        newLastName: 'B'
      },
      {
        newId: 2,
        newFirstName: 'C',
        newLastName: 'D'
      }
    ]
    */
    

    What transform does:

    • It turns the data from the form {oldId: 1, oldFirstName: 'A', oldLastName: 'B', unimportant: 'x'} into [['oldId', 1], ['oldFirstName', 'A'], ['oldLastName', 'B'], ['unimportant', 'x']] using Object.entries, so that we can use array methods on it.
    • It cuts off any entries beyond the number of "new keys" specified using slice, so that the "unimportant data" won't get processed, so [['oldId', 1], ['oldFirstName', 'A'], ['oldLastName', 'B'], ['unimportant', 'x']] becomes [['oldId', 1], ['oldFirstName', 'A'], ['oldLastName', 'B']].
    • It maps all the entries from [key, value] to [newKey, value], looking up newKey from the newKeys array based on the index of the current entry (the how-many-th it is in the object), so [['oldId', 1], ['oldFirstName', 'A'], ['oldLastName', 'B']] becomes [['newId', 1], ['newFirstName', 'A'], ['newLastName', 'B']].
    • It turns the modified data from the form [['newId', 1], ['newFirstName', 'A'], ['newLastName', 'B']] back into the structure {newId: 1, newFirstName: 'A', newLastName: 'B'} using Object.fromEntries.

    At the end we just call this transformation on all elements of your array using map.

    Note: If your ECMAScript version doesn't have Object.fromEntries, you can use a polyfill: Object.fromEntries = a => a.reduce((o, [k, v]) => Object.assign(o, { [k]: v }), {})