0

Because I'm dealing with a relatively big object, I want to be able to modify my object value dynamically by defining a "path".

let a="x", b="y", c="z"

let objKeys = [a, b, c]

let value = 5

obj = {x: 
        {y: 
          {z: 1
          }
         }
       }


I want to be able to achieve this.

obj[a][b][c] = value;

Is there any way to do this? I tried obj(eval(`["a"]["b"]["c"]`)) = value but it says that "invalid left-hand side in assignment".

3
  • 2
    It is totally unclear what you are asking, and also what you are trying to achieve here. Commented May 16, 2019 at 19:09
  • Can you give us an example use case? What you start with and what you expect to end up with? Commented May 16, 2019 at 19:11
  • Your maps this example is not an object that has key/value pairs. So when you say map out my object properties so that I can modify my object values you have made no sense at all. Objects that have key/values pairs are structured like this: {key:value}. What you have shown in that example is a list represented as an Array. That is part of the reason your question is unclear. Please try to edit your question so we can understand your intent. Commented May 16, 2019 at 19:26

4 Answers 4

2

You can achieve this by using the array reduce function:

const objProps = ["a","b","c"]
const value = 5
const newObj = objProps.reverse().reduce((result, curProp)=> (
{
    [curProp]: result
  }
), value)

console.log(newObj)

This will "chain" the prop inside of each other, starting with the last value in objProps. Because you want to use names as indices use an object instead of array.

EDIT: ok, so I read your question again and as I understood you don't want to create a new object but modify values inside of a big object by defining a path. For this have a look at lodash. This library has a method set where you can provide a path to the location of the property and set a new value (https://lodash.com/docs/4.17.11#set).

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

Comments

1

By using an array of keys and an object, you could reduce this object by accessing the object with each key and return the final object. Then take the last key and assign the value.

This approach add a new object as a default value for not given properties.

function setValue(object, keys, value) {
    var target = keys.pop();
    keys.reduce((o, k) => o[k] = o[k] || {}, object)[target] = value;
}

var obj = { x: { y: { z: 1 } } };

setValue(obj, ['x', 'y', 'z'], 5);

console.log(obj);

Comments

1
let obj = {
  a: {
    b: {
      c: 'hey',
    }
  }
}

let objProps = ["a", "b", "c"];

function findValue(obj, objProps, index = 0) {
  if (index > objProps.length-1) return obj;
return findValue(obj[objProps[index]],objProps, index+1)
}

findValue(obj, objProps)
let obj = {
  a: {
    b: {
      c: 'hey',
    }
  }
}

let objProps = ["a", "b", "c"];

function assignValue(obj, objProps, newValue, index = 0) {
  console.log(obj)
  if (index >= objProps.length-1 && obj[objProps[index]]) {
    return obj[objProps[index]] = newValue;
    } else {

return assignValue(obj[objProps[index]],objProps, newValue, index+1)
  }
}

assignValue(obj, objProps, "asdsa")

1 Comment

@minimic are you trying to find value or assign?
0

A quick solution i crafted, i'm sure you can make it work with eval, if you show us the actual value's i can try and post a solution with that

However for this hack:

let objProps = ['a', 'b', 'c'];
let value = ?;
let tmp;
let result = objProps.reduce((acc, curr) => {
    let tmp_v2 = acc;
    while (Object.keys(tmp).length > 0) {
        tmp_v2 = tmp[Object.keys(tmp_v2)[0]]
    }
    tmp_v2[curr] = {};
    tmp = tmp_v2;
    return acc
}, {})
tmp.c = value;

now result would look like:

{
  "a": {
    "b": {
      "c": value
    }
  }
}

as wanted.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.