【问题标题】:Javascript update values in nested object by array pathJavascript通过数组路径更新嵌套对象中的值
【发布时间】:2019-04-29 02:02:06
【问题描述】:

给定嵌套对象:

{
    name: 'UK',
    toggled: false,
    active: false,
    children: [{
            name: 'Region 1',
            active: false,
            toggled: false,
            children: [{
                    name: 'Heathrow T1',
                    toggled: false,
                    active: false,
                    children: []
                },
                {
                    name: 'HTT',
                    toggled: false,
                    active: false,
                    children: []
                },
            ]
        },
        {
            name: 'Region 2',
            active: false,
            toggled: false,
            children: [{
                name: Gatwick North,
                active: false,
                toggled: false,
                children: []
            }]
        }
    ]
}

和给定的路径

['UK', 'Region 2', 'Gatwick North']

我怎样才能设法为匹配上述数组的嵌套对象中的路径添加活动/切换属性为 true。

输出应该如下:

{
    name: 'UK',
    toggled: true,
    active: true,
    children: [{
            name: 'Region 1',
            active: false,
            toggled: false,
            children: [{
                    name: 'Heathrow T1',
                    toggled: false,
                    active: false,
                    children: []
                },
                {
                    name: 'HTT',
                    toggled: false,
                    active: false,
                    children: []
                },
            ]
        },
        {
            name: 'Region 2',
            active: true,
            toggled: true,
            children: [{
                name: 'Gatwick North',
                active: true,
                toggled: true,
                children: []
            }]
        }
    ]
}

我试图通过递归来实现这一点,但到目前为止没有成功。我正在搜索问题,但没有一个符合我目前的情况。

【问题讨论】:

  • 请展示您的尝试,而不是仅仅写下您所做的。

标签: javascript loops recursion nested traversal


【解决方案1】:

使用递归的简单示例,解释在代码中作为 cmets

const obj = {name: 'UK',toggled: false,active: false,children: [{name: 'Region 1',active: false,toggled: false,children: [{name: 'Heathrow T1',toggled: false,active: false,children: []},{name: 'HTT',toggled: false,active: false,children: []},]},{name: 'Region 2',active: false,toggled: false,children: [{name: 'Gatwick North',active: false,toggled: false,children: []}]}]};

const checkAndChange = (obj) => { // function that will check if name exists in array and change toggle and active properties
  const arr = ['UK', 'Region 2', 'Gatwick North'];
  if (arr.includes(obj.name)) {
    obj.toggled = true;
    obj.active = true;
  }
}

const recursion = (obj) => {
   const o = obj;
   checkAndChange(o); // check if name exists in array and change toggle and active properties
   if (o.children.length > 0) { // check if has children
   		o.children.forEach(v => { // if has children do the same recursion for every children
      	recursion(v);
      });
   }
   return o; // return final new object
}

console.log(recursion(obj));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    使用递归方法查找路径并更新值。

    var obj = [{name: 'UK',toggled: false,active: false,children: [{name: 'Region 1',active: false,toggled: false,children: [{name: 'Heathrow T1',toggled: false,active: false,children: []},{name: 'HTT',toggled: false,active: false,children: []},]},{name: 'Region 2',active: false,toggled: false,children: [{name: 'Gatwick North',active: false,toggled: false,children: []}]}]}];
    
    function FilterArray(temp2,i){
     temp2.filter(function(el){
          if(el['name']==path[i]){
             el['toggled']=true;
              el['active']=true;
            if(i!=path.length-1){
              FilterArray(el['children'],++i);
            }
          }
      });
    }
    
    console.log("Before");
    console.log(obj);
    var path=['UK', 'Region 2', 'Gatwick North'];
    FilterArray(obj,0);
    
    console.log("After");
    console.log(obj);

    【讨论】:

    • 你的例子不起作用,属性仍然是错误的
    • @ArtyomAmiryan 我认为只有最后一个孩子的切换应该是真的。现在编辑了代码,请检查
    • 数据集应该是一个对象,而不是一个数组
    【解决方案3】:

    基于this answer 非常similar question

    function deep_value(obj, path){
        for (var i=0; i<path.length; i++){
            obj = obj[path[i]];
        };
        return obj;
    };
    

    像这样使用它:

    var obj = {
      foo: { bar: 'baz' }
    };
    
    alert(deep_value(obj, ['foo','bar'])); // alerts "baz"
    

    Extra:同样的函数也可以用于数组

    var arr = [
      ['item 0.0', 'item 0.1'],
      ['item 1.0', 'item 1.1'],
      ['item 2.0', 'item 2.1'],
    ]
    console.log(deep_value(arr, [2,1])); // logs "item 2.1"
    

    Codepen

    【讨论】:

      【解决方案4】:

      这适用于嵌套数组。

      参数:
      - array:要更新的数组
      - path: 更新内容 ([0] - array[0], [2,1] - array[2][1], etc.)
      - data:要分配的数据

          function updateArray(array, path, data) {
              const index = path.shift();
              if (path.length) {
                  if (!Array.isArray(array[index])) {
                      array[index] = [];
                  }
                  updateArray(array[index], path, data);
              } else {
                  array[index] = data;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2021-11-27
        • 2011-09-23
        • 1970-01-01
        相关资源
        最近更新 更多