将值添加到具有基于数组的键深度的对象

时间:2019-05-02 15:14:20

标签: javascript reactjs

我有一个数组。可以说是

const array = ["lvl1", "lvl2", "lvl3", "key"]

我很有价值。可以说是

const value = false

我有一个物体。可以说是

const object = {
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "meow",
      lvl3: {
        cows: "moo"
        key: true
      }
    }
  }
}

我如何创建一个接受arrayvalue的函数,然后更新对象,以便更新数组(数组的最后一项)中的key使用新的value?需要根据数组中的前array.length - 1个字符串适当地嵌套它。

例如,我们将其称为函数createObject。如果我使用上面已经定义为arrayvalue的话来命名它:

const newObject = createObject(array, value)

然后newObject应该等于:

{
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "meow",
      lvl3: {
        cows: "moo"
        key: false
      }
    }
  }
}

这是另一个具有不同嵌套级别的示例:

const updatedObject = createObject(["lvl1", "lvl2", "cats"], "stink")

然后updatedObject应该等于:

{
  lvl1: {
    dogs: "bark",
    lvl2: {
      cats: "stink",
      lvl3: {
        cows: "moo"
        key: true
      }
    }
  }
}

我已经走了这么远,但没有用:

import object from "./object"

const createObject = (array, value) => {
  let results = object;
  for (let i = 0; i < array.length; i++) {
    i === array.length - 1
      ? (results = results[array[i]] = {
          ...results[array[i]],
          [array[i]]: value
        })
      : (results = results[array[i]] = {
          ...results[array[i]],
          [results[array[i]]]: {}
        });
    }
  return results;
}

我不想更改初始对象。我想返回一个新对象。而且我不会在对象上添加任何新的键/值对,而只会更改现有的键/值对。

2 个答案:

答案 0 :(得分:2)

这有点通用,因为它不假定源是名为object的全局变量:

let array = ["lvl1", "lvl2", "lvl3", "key"];
let value = false;

let createObject = (keys, value) => {
  let o, obj = o = {};
  let lastKey = keys.pop();
  keys.forEach(key => o = o[key] = o[key] || {});
  o[lastKey] = value;
  return obj;
};

let addToObject = (obj, keys, value) => {
  let o, copy = o = JSON.parse(JSON.stringify(obj));
  let lastKey = keys.pop();
  keys.forEach(key => o = o[key] = o[key] || {});
  o[lastKey] = value;
  return copy;
};

let x = createObject(array, value);
let y = addToObject(x, ['lvl1'], 3);
let z = addToObject(y, ['a', 'b', 'c'], 4);

console.log(x);
console.log(y);
console.log(z);

答案 1 :(得分:0)

您可以获取条目并构建新对象,并检查实际键是否等于数组的第一项,然后还检查其余数组的长度并获取值。对于嵌套副本,请检查对象,然后通过再次调用该函数来构建新的更深层次。

function getObject(object, [key, ...keys], value) {
    return Object.assign({}, ...Object
        .entries(object)
        .map(([k, v ]) => ({ [k]: k === key && !keys.length
            ? value
            : v && typeof v === 'object'
                ? getObject(v, k === key ? keys : [], value)
                : v
        })),
        Object.keys(object).includes(key) || { [key]: keys.length
            ? getObject({}, keys, value)
            : value
        }
    );
}

const
    object1 = { lvl1: { dogs: "bark", lvl2: { cats: "meow", lvl3: { cows: "moo", key: true } } } },
    object2 = getObject(object1, ["lvl1", "lvl2", "lvl3", "key"], false),
    object3 = getObject(object2, ["lvl1", "lvl2", "cats"], "stink"),
    object4 = getObject({}, ["lvl1", "lvl2", "cats"], "stink");;

console.log(object1);
console.log(object2);
console.log(object3);
console.log(object4);
.as-console-wrapper { max-height: 100% !important; top: 0; }