Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating object properties with array elements

I have an object with nested properties. I want to update those nested properties by using an array of elements that reflect the nested sequence of the object. Also if a property does not exist, then add it, otherwise only update it.

Problem: is that I got all properties separated (non nested) with just empty objects ...

This is the function I tried implementing

function myFunction(myObject, ...myArrray) {

    let value = myArrray.pop()

    for (let i = 0; i < myArrray.length; i++) {
        const element = myArrray[i]
        if (!myObject.hasOwnProperty(element)) {
            if (i == myArrray.length)
                myObject[element] = value
            else
                myObject[element] = {}
        }
        else {
            myObject[element] = myObject[i + 1]
        }
    }
    return myObject
}
const myLocalStorage = {
    users: {
        theme: 'westeros',
        notifications: {
            email: true,
            push: {
                infos: true
            }
        }
    },
    admins: {
        // admin properties
    }
}

Updating "email" property (which exists)


const array1 = ["users", "notification", "email", false]
myFunction(myLocalStorage, array1)
  • Adding "sms" property (which does not exist)

const array2 = ["users", "notification", "sms", true]
myFunction(myLocalStorage, array2)
like image 639
a6e b0a Avatar asked Jul 11 '26 23:07

a6e b0a


1 Answers

There are multiple issues with your code; most importantly you need to update the object you'll assign to, following the path you have followed to the current point.

In the following implementation, I defined the targetObject variable that follows the path from myObject up to the penultimate key (targetObject = targetObject[key]); all those values (targetObject[key]) need to be Objects. Then the targetObject will be assigned the value at the final key:

function myFunction(myObject, myArray) {
    const value = myArray.pop();
    let targetObject = myObject;
    for (let i = 0; i < myArray.length - 1; i++) {
        const key = myArray[i];
        if(!(targetObject[key] instanceof Object)){
            targetObject[key] = {};
        }
        targetObject = targetObject[key];
    }
    const key = myArray[myArray.length - 1];
    targetObject[key] = value;

    return myObject;  // not necessary if we have the original array  
}

Demo snippet:

function myFunction(myObject, myArray) {
    const value = myArray.pop();
    let targetObject = myObject;
    for (let i = 0; i < myArray.length - 1; i++) {
        const key = myArray[i]
        if(!(targetObject[key] instanceof Object)){
            targetObject[key] = {};
        }
        targetObject = targetObject[key];
    }
    const key = myArray[myArray.length - 1];
    targetObject[key] = value;

    return myObject;
}

const myLocalStorage = {
    users: {
        theme: 'westeros',
        notifications: {
            email: true,
            push: {
                infos: true
            }
        }
    },
    admins: {
        // admin properties
    }
}

const array1 = ["users", "notifications", "email", false];
myFunction(myLocalStorage, array1);

const array2 = ["users", "notifications", "sms", true]
myFunction(myLocalStorage, array2)

console.log(myLocalStorage);

This can be written somewhat more concisely using Array#reduce:

function myFunction(myObject, myArray) {
    const value = myArray.pop();
    const lastKey = myArray.pop();
    const innerObject = myArray.reduce((targetObject, key) => {
        if(!(targetObject[key] instanceof Object)){
            targetObject[key] = {};
        }
        return targetObject[key];
    }, myObject );
    innerObject[lastKey] = value;
}

The same effect can be obtained through recursion, by calling recursively myFunction with an object ever more deep inside the structure of the original object and with an array ever smaller:

function myFunction(myObject, myArray){
    if(myArray.length === 0){
        return;
    }
    const key = myArray.shift();
    if(myArray.length === 1){
        myObject[key] = myArray[0];
    }
    else{
        if(!(myObject[key] instanceof Object)){
            myObject[key] = {}
        }
        myFunction(myObject[key], myArray);
    }
}

Demo snippet:

function myFunction(myObject, myArray){
    if(myArray.length === 0){
        return;
    }
    const key = myArray.shift();
    if(myArray.length === 1){
        myObject[key] = myArray[0];
    }
    else{
        if(!(myObject[key] instanceof Object)){
            myObject[key] = {}
        }
        myFunction(myObject[key], myArray);
    }
}

const myLocalStorage = {
    users: {
        theme: 'westeros',
        notifications: {
            email: true,
            push: {
                infos: true
            }
        }
    },
    admins: {
        // admin properties
    }
}

const array1 = ["users", "notifications", "email", false]
myFunction(myLocalStorage, array1);

const array2 = ["users", "notifications", "sms", true]
myFunction(myLocalStorage, array2)

console.log(myLocalStorage);
like image 123
kikon Avatar answered Jul 14 '26 13:07

kikon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!