【问题标题】:Finding and updating an object, returning the whole object, recursively递归查找和更新对象,返回整个对象
【发布时间】:2021-08-26 21:42:50
【问题描述】:

我一直在尝试递归,似乎我可以接近我的预期,但是,我被困在更新后返回整个对象。

举个例子,您有一个对象,其中包含一个数组,其中包含您想要更新值的键...

const testObj = {
    data: {
        dataNested: {
            dataNestedNested: "Hello",
            amITrue: false
        }
    },
    data2: {
        dataNested2: {
            dataNestedNested2: "Hello",
            amITrue2: false
        }
    },
    data3: {
        dataNested3: {
            dataNestedNested3: "Hello",
            amITrue3: false
        }
    }
}

const scopeArray = ["data2", "dataNested2", "dataNestedNested2"]

更新目标键/值之后,您将如何将对象作为一个整体返回。这是我构建的...

    const findAndUpdate = (obj, array, key, i, value) => {
      if (i === array.length - 1) {
        obj = { ...obj, [key]: value };
        console.log(obj);
      } else {
        i++;
        findAndUpdate(obj[key], array, array[i], i, value);
      }
    };
    findAndUpdate(testObj, scopeArray, scopeArray[0], 0, "World");

console.log 输出

> {dataNestedNested2: "World", amITrue2: false}

【问题讨论】:

    标签: javascript reactjs recursion state


    【解决方案1】:

    遍历键并减少对象。

    const testObj = { data: { dataNested: { dataNestedNested: "Hello", amITrue: false } }, data2: { dataNested2: { dataNestedNested2: "Hello", amITrue2: false } }, data3: { dataNested3: { dataNestedNested3: "Hello", amITrue3: false } } }
    const scopeArray = ["data2", "dataNested2", "dataNestedNested2"]
    
    function findAndUpdate(object, keys, value) {
        const lastKey = keys.pop();
        let mod = keys.reduce((o, k) => o[k], object);
        mod[lastKey] = value;
        return mod;
    }
    
    let value = findAndUpdate(testObj, scopeArray, "World");
    console.log(value);

    【讨论】:

      【解决方案2】:

      您是否要返回整个testObject 或内部对象{dataNestedNested2: "Hello", amITrue2: false}} 的更新版本还不是很清楚。如果是前者,我有一个 function I use oftensetPath,虽然签名略有不同,但似乎完全符合您的要求。

      const setPath = ([p, ...ps]) => (v) => (o) =>
        p == undefined ? v : Object .assign (
          Array .isArray (o) || Number .isInteger (p) ? [] : {},
          {...o, [p]: setPath (ps) (v) ((o || {}) [p])}
        )
      
      const testObj = {data: {dataNested: {dataNestedNested: "Hello", amITrue: false}}, data2: {dataNested2: {dataNestedNested2: "Hello", amITrue2: false}}, data3: {dataNested3: {dataNestedNested3: "Hello", amITrue3: false}}}
      const scopeArray = ['data2', 'dataNested2', 'dataNestedNested2']
      
      console .log (setPath (scopeArray) ('World') (testObj))
      .as-console-wrapper {max-height: 100% !important; top: 0}

      签名的结构是我喜欢的工作方式:完全柯里化,值更可能发生变化,然后是那些不太可能发生变化的值。但是如果你想要一个单独的调用来传递对象、作用域路径和值,就像这样:findAndUpdate (testObj, scopeArray, 'World'),我们可以包装这个:

      const findAndUpdate = (obj, array, val) =>
        setPath (array) (val) (obj)
      

      或者重写

      const findAndUpdate = (o, [p, ...ps], v) =>
        p == undefined ? v : Object .assign (
          Array .isArray (o) || Number .isInteger (p) ? [] : {},
          {...o, [p]: findAndUpdate ((o || {}) [p], ps, v)}
        )
      

      【讨论】:

      • 我知道您应该使用 cmets 要求澄清,但我将反对这一点并亲自感谢您。这是一个完美的功能。谢谢你,先生,你应该加薪。
      • 很高兴你喜欢它。不知何故,我失去了一大段解释。如果我很快找到时间,我会回来并再次添加它。关于那次加薪……你认识我的老板吗? ;-)
      猜你喜欢
      • 2019-11-01
      • 2019-01-31
      • 2013-04-29
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2017-04-15
      相关资源
      最近更新 更多