Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/465.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中递归嵌套属性的创建_Javascript_Recursion - Fatal编程技术网

JavaScript中递归嵌套属性的创建

JavaScript中递归嵌套属性的创建,javascript,recursion,Javascript,Recursion,我正试图基于MongoDB ish选择器“top.middle.bottom”递归地构建一个具有属性树的对象。还有一些下划线帮助程序: function setNestedPropertyValue(obj, fields, val) { if (fields.indexOf(".") === -1) { // On last property, set the value obj[fields] = val; return obj; // Recurse bac

我正试图基于MongoDB ish选择器“top.middle.bottom”递归地构建一个具有属性树的对象。还有一些下划线帮助程序:

function setNestedPropertyValue(obj, fields, val) {
  if (fields.indexOf(".") === -1) { 
    // On last property, set the value
    obj[fields] = val; 
    return obj; // Recurse back up
  } else {
    var oneLevelLess = _.first(fields.split("."));
    var remainingLevels = _.rest(fields.split(".")).join(".");
    // There are more property levels remaining, set a sub with a recursive call
    obj[oneLevelLess] = setNestedPropertyValue( {}, remainingLevels, val);
  }
}

setNestedPropertyValue({}, "grandpaprop.papaprop.babyprop", 1);
期望的:

{ 
  grandpaprop: {
    papaprop: {
      babyprop: 1
    }
  }
}
结果:

undefined

帮助和提示将不胜感激。

正如杰克在问题中提到的,我没有在
else
语句的最后一行返回我的对象。通过添加此项,它现在可以工作了:

 obj[oneLevelLess] = setNestedPropertyValue( {}, remainingLevels, val);
   return obj; // Add this line
 }

正如Jack在问题中提到的,我没有在
else
语句的最后一行返回我的对象。通过添加此项,它现在可以工作了:

 obj[oneLevelLess] = setNestedPropertyValue( {}, remainingLevels, val);
   return obj; // Add this line
 }

我会选择迭代解决方案,而不是递归:

function setNestedPropertyValue(obj, fields, val)
{
  fields = fields.split('.');

  var cur = obj,
  last = fields.pop();

  fields.forEach(function(field) {
      cur[field] = {};
      cur = cur[field];
  });

  cur[last] = val;

  return obj;
}

setNestedPropertyValue({}, "grandpaprop.papaprop.babyprop", 1);

我会选择迭代解决方案,而不是递归:

function setNestedPropertyValue(obj, fields, val)
{
  fields = fields.split('.');

  var cur = obj,
  last = fields.pop();

  fields.forEach(function(field) {
      cur[field] = {};
      cur = cur[field];
  });

  cur[last] = val;

  return obj;
}

setNestedPropertyValue({}, "grandpaprop.papaprop.babyprop", 1);
编辑

这是另一个版本,感谢Scott Sauyet的建议:

函数设置路径(obj,[first,…rest],val){
如果(rest.length==0){
返回{…obj[first]:val}
}
设nestedObj=obj[first]|{};
返回{…obj[first]:setPath(nestedObj,rest,val)};
}
函数setNestedPropertyValue(对象、字段、值){
返回设置路径(对象,字段分割('.'),val);
}
//范例
设test_obj={};
测试对象=设置的嵌套属性值(测试对象,“foo.bar.baz”,1);
test_obj=setNestedPropertyValue(test_obj,“foo.bar.baz1”,1);
//将输出{“foo”:{“bar”:{“baz”:1,“baz1”:1}}},而在原始版本中仅设置“baz1”
log(JSON.stringify(test_obj))编辑

这是另一个版本,感谢Scott Sauyet的建议:

函数设置路径(obj,[first,…rest],val){
如果(rest.length==0){
返回{…obj[first]:val}
}
设nestedObj=obj[first]|{};
返回{…obj[first]:setPath(nestedObj,rest,val)};
}
函数setNestedPropertyValue(对象、字段、值){
返回设置路径(对象,字段分割('.'),val);
}
//范例
设test_obj={};
测试对象=设置的嵌套属性值(测试对象,“foo.bar.baz”,1);
test_obj=setNestedPropertyValue(test_obj,“foo.bar.baz1”,1);
//将输出{“foo”:{“bar”:{“baz”:1,“baz1”:1}}},而在原始版本中仅设置“baz1”

log(JSON.stringify(test_obj))
在第二个分支中没有返回
obj
。也就是说,你为什么要首先使用递归?可能是@Jack的复制品,使用递归是因为我觉得它很有趣,而且(显然)我需要练习一下。@FelixKling,谢谢你提到这个问题。我猜这就是Jack暗示的方法。在第二个分支中,您不会返回
obj
。也就是说,你为什么要首先使用递归?可能是@Jack的复制品,使用递归是因为我觉得它很有趣,而且(显然)我需要练习一下。@FelixKling,谢谢你提到这个问题。我想这就是杰克暗示的方法。对我来说,第三颗子弹是一个严重的负面影响。变异输入数据是魔鬼的工作!:-)我自己的非变异版本可能类似这样的函数,为
字段
const setPath=(obj,[f,…fs],val)=>f==未定义?obj:{…obj[f]:fs.length?setPath(obj[f]|{},fs,val):val}
,使用点分隔字符串进行包装:
const setNestedPropertyValue=(obj,field,val)=>setPath(obj,field.split('.'),val)
。它不是特别复杂,我维护的库做得更多,但对于这里的情况来说已经足够了。@ScottSauyet哈哈,我完全同意对输入数据进行变异:)我只是说它比原始版本稍微改进了一点,这是两者的奇怪混合。谢谢你的建议!我最近只玩了一点JS,还没有遇到spread/rest操作符。我已经根据你的建议更新了我的答案。我只是更喜欢一种更详细的方法,这样我就可以了解正在发生的事情……Rest/spread可以干涸很多代码。这绝对值得研究。对我来说,第三颗子弹是一个严重的负面影响。变异输入数据是魔鬼的工作!:-)我自己的非变异版本可能类似这样的函数,为
字段
const setPath=(obj,[f,…fs],val)=>f==未定义?obj:{…obj[f]:fs.length?setPath(obj[f]|{},fs,val):val}
,使用点分隔字符串进行包装:
const setNestedPropertyValue=(obj,field,val)=>setPath(obj,field.split('.'),val)
。它不是特别复杂,我维护的库做得更多,但对于这里的情况来说已经足够了。@ScottSauyet哈哈,我完全同意对输入数据进行变异:)我只是说它比原始版本稍微改进了一点,这是两者的奇怪混合。谢谢你的建议!我最近只玩了一点JS,还没有遇到spread/rest操作符。我已经根据你的建议更新了我的答案。我只是更喜欢一种更详细的方法,这样我就可以了解正在发生的事情……Rest/spread可以干涸很多代码。这绝对值得研究。