【问题标题】:filter nested tree object without losing structure过滤嵌套树对象而不丢失结构
【发布时间】:2016-12-24 09:57:55
【问题描述】:

我有嵌套的树对象,我想过滤而不丢失结构

var items = [
    {
        name: "a1",
        id: 1,
        children: [{
            name: "a2",
            id: 2,
            children: [{
                name: "a3",
                id: 3
            }]
        }]
    }
];

例如,如果 id == 2 删除 id 为 2 的对象和他的孩子

如果 id == 3 仅删除 id 为 3 的对象

这只是一个让问题变得干净的对象,但它自身包含的对象越来越多:)

使用 vanilla javascript、_lodash 或 Angular2 没关系

谢谢你

【问题讨论】:

  • 你需要一个 filtered 对象,我的意思是一个不影响给定数组的新对象,还是只是没有删除项的数组?这是过滤与删除的问题。
  • 没有被删除项目的数组:)

标签: javascript filter nested


【解决方案1】:

您可以使用filter() 创建递归函数,如果值为 Array,还可以继续过滤子级。

var items = [{
  name: "a1",
  id: 1,
  children: [{
    name: "a2",
    id: 2,
    children: [{
      name: "a3",
      id: 3
    }, ]
  }]
}];

function filterData(data, id) {
  var r = data.filter(function(o) {
    Object.keys(o).forEach(function(e) {
      if (Array.isArray(o[e])) o[e] = filterData(o[e], id);
    })
    return o.id != id
  })
  return r;
}

console.log(filterData(items, 3))
console.log(filterData(items, 2))

更新:正如 Nina 所说,如果您知道 children 是带有数组的属性,则不需要循环键,您可以直接定位 children 属性。

var items = [{
  name: "a1",
  id: 1,
  children: [{
    name: "a2",
    id: 2,
    children: [{
      name: "a3",
      id: 3
    }, ]
  }]
}];

const filterData = (data, id) => data.filter(o => {
  if (o.children) o.children = filterData(o.children, id);
  return o.id != id
})

console.log(JSON.stringify(filterData(items, 3), 0, 2))
console.log(JSON.stringify(filterData(items, 2), 0, 2))

【讨论】:

  • 如果您知道 children 是具有数组的属性,那么迭代键是非常多余的。
  • 另外,Array.filter 应该像 Object.keys(o).forEach() 一样遍历每个项目。但是当找到需要的id id 时,我们可以提前出去(返回)
  • 感谢您的回答,但我想在这里获取一个孩子的父母,例如,如果主数组有更多对象,它会在没有选定孩子的情况下返回所有对象,但我想返回特定孩子的唯一父母看这个代码笔codepen.io/Kosrat/pen/QWWqNoW?editors=1111我只想得到a1和a2
  • 副作用?带有 mutate items 的函数
【解决方案2】:

如果您的情况可以使用 Lodash+Deepdash,那么:

let filtered = _.filterDeep(items,(i)=>i.id!=3,{tree:true});

这是demo Codepen

【讨论】:

    【解决方案3】:

    您可以对Array#some 使用迭代方法,并为子级调用回调iter 递归。我找到了,拼接。

    function deleteItem(id) {
        items.some(function iter(a, i, aa) {
            if (a.id === id) {
                aa.splice(i, 1);
                return true;
            }
            return a.children.some(iter);
        });
    }
    
    var items = [{ name: "a1", id: 1, children: [{ name: "a2", id: 2, children: [{ name: "a3", id: 3 }] }] }];
    
    console.log(items);
    deleteItem(3);
    console.log(items);
    deleteItem(2);
    console.log(items);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案4】:

      使用递归函数:

      var items = [
          {
              name: "a1",
              id: 1,
              children: [{
                  name: "a2",
                  id: 2,
                  children: [{
                      name: "a3",
                      id: 3,
                      children: [{
                          name: "a4",
                          id: 4,
                      }]
                  }]
              }]
          }
      ];
      
      function filterId(items, id) {
        var len = items.length;
        while (len--) {
          if (items[len].id === id) {
            items.splice(len, 1);
            break;
          } else {
            filterId(items[len].children, id);
          }
        }
        return items;
      }
      
      // filtering out the item with 'id' = 4
      console.log(filterId(items, 4));
      
      // filtering out the item with 'id' = 2
      console.log(filterId(items, 2));

      【讨论】:

        猜你喜欢
        • 2019-12-04
        • 1970-01-01
        • 1970-01-01
        • 2022-08-03
        • 1970-01-01
        • 1970-01-01
        • 2020-07-28
        相关资源
        最近更新 更多