skip to Main Content

I have object pivot, that has multiple accessors of different depths.

For keys array const keys = ['rotation'] I want my code to assign value x like this:

pivot['rotation'] = x

And for array const keys = ['rotation', 'y'] I want the code to do this:

pivot['rotation']['y'] = x

Solution I tried looks like this:

accessors.forEach(a => accessor = accessor[a])
accessor = x

However, after logging the accessor value, I found out it’s just primitive value of 0.1, instead of an object reference.

Can I get the object reference somehow? Or do I need to go a different path to achieve this?

Working code would also be something ugly like next example, which is not acceptable.

if (accessors.length == 1) {
    pivot[accessors[0]] = x
} else if (accessors.length == 2) {
    pivot[accessors[0]][accessors[1]] = x
}

2

Answers


  1. You couldd reduce the array of keys and preserve the last key as accessor for assigning the value.

    const
        setValue = (reference, keys, value) => {
            const last = keys.pop();
            keys.reduce((o, k) => o[k] ??= {}, reference)[last] = value;
        },
        pivot = {};
    
    setValue(pivot, ['rotation', 'x'], 'y');
    
    console.log(pivot);
    Login or Signup to reply.
  2. here is something similar to lodash set. keep in mind this mutates the object

    const pivot = {}
    
    const set = (obj, path, value) => {
      // Regex explained: https://regexr.com/58j0k
      const pathArray = Array.isArray(path) ? path : path.match(/([^[.]])+/g)
      const pathLength = pathArray.length;
      pathArray.reduce((acc, key, i) => {
        if (acc[key] === undefined) acc[key] = {}
        if (i === pathLength - 1) acc[key] = value
        return acc[key]
      }, obj)
    }
    set(pivot, ['rotation', 'x'], 'y');
    
    console.log(pivot);

    since your path is already an array you don’t need the regex part

    const pivot = {}
    const set = (obj, path, value) => {
      const pathLength = path.length;
      path.reduce((acc, key, i) => {
        if (acc[key] === undefined) acc[key] = {}
        if (i === pathLength - 1) acc[key] = value
        return acc[key]
      }, obj)
    }
    
    set(pivot, ['rotation', 'x'], 'y');
    
    console.log(pivot);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search