如何重构/修复算法,从将引用变异为使用内联变量

问题描述 投票:2回答:1

该函数采用a.b.c之类的输入路径,并应输出嵌套结构json,如:

{
   a: {
      b: {
         c: {}
      }
   }
}

使用迭代样式的算法是:

function stringToObj(path, obj) {
  var parts = path.split(".");
  var part;
  while ((part = parts.shift())) {
    if (typeof obj[part] != "object") obj[part] = {};
    obj = obj[part]; // line 6
  }
}

当前用法:

let result = {};
stringToObj("a.b.c", result);
console.log(result); // outputs the json

JsFiddle

问题:

它依赖于在第6行上更改obj参数。我不想不依赖传递result对象,而是在函数内部创建一个对象。这样做会导致不同的结果。所需的示例用法:

const result = stringToObj("a.b.c"); // result should be the json

上下文:

该练习仅供学习。主要目的是理解为什么按以下步骤删除obj并重写函数无法按预期工作:

function stringToObj(path) {
  var obj = {};
  var parts = path.split(".");
  var part;
  while ((part = parts.shift())) {
    if (typeof obj[part] != "object") obj[part] = {};
    obj = obj[part]; // line 6
  }
  return obj;
}
javascript algorithm
1个回答
5
投票

除以.后,可以使用reduceRight从最后一个属性c开始,同时获取一个空对象的初始值。在回调内部,使用计算属性返回一个新对象,该对象包含正在迭代的属性处的旧对象:

const stringToObj = str => str.split('.').reduceRight(
  (lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));

如果您不熟悉它,则reduceRight类似于reduce,不同之处在于它从数组的最后一个元素开始并向后进行迭代,而不是从数组的第一个元素开始并向后进行迭代。在每次迭代中,都会调用回调,其中第一个参数(此处为lastObj)是last迭代返回的值,第二个参数是要迭代的数组的当前项。

您还可以reverse属性数组并使用reduce而不是reduceRight,这乍一看可能会更容易理解,但是它不太优雅:

const stringToObj = str => str.split('.').reverse().reduce(
  (lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));

也请不要混合使用varlet。如果要使用ES2015语法-您应使用-考虑始终使用const,而仅使用let when you must reassign。永远不要使用var,它有太多陷阱值得在现代代码中使用。

© www.soinside.com 2019 - 2024. All rights reserved.