递归过滤和删除对象数组中的项目 [英] Recursively filter and delete item in array of objects

查看:48
本文介绍了递归过滤和删除对象数组中的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试深度过滤,直到找到具有 id 的特定对象.我已经参考了这些参考资料,

  1. 递归过滤对象数组
  2. 过滤对象数组中的项目
  3. 递归过滤具有不同属性的对象数组
  4. 使用 JavaScript 从数组中删除对象

我能够找到父节点,但无法删除特定的子节点.我在这里做错了什么?

有效载荷,

<预><代码>[{编号:1,名称:史莱克",锁:假,检查:错误,选择:假,层:[],},{编号:2,姓名:菲奥娜",锁:假,检查:错误,选择:假,层数:[{编号:4,名称:法夸德勋爵",锁:假,检查:错误,选择:假,层数:[{编号:5,名称:《白马王子》,锁:假,检查:错误,选择:假,层:[],},],},],},{编号:3,名称:驴",锁:假,检查:错误,选择:假,层:[],},]

我正在使用此代码获取父节点,但不确定从哪里拼接.

this.layers.filter(function f(o: any) {if (o.id == 5) 返回真;如果 (o.layers) 返回 (o.layers = o.layers.filter(f)).length;});

预期输出:

<预><代码>[{编号:1,名称:史莱克",锁:假,检查:错误,选择:假,层:[],},{编号:2,姓名:菲奥娜",锁:假,检查:错误,选择:假,层数:[{编号:4,名称:法夸德勋爵",锁:假,检查:错误,选择:假,层:[],},],},{编号:3,名称:驴",锁:假,检查:错误,选择:假,层:[],},]

解决方案

我会尝试在可重用函数的基础上构建它.我从另一个答案中抽象了一个deepFilter,以便我们可以配置子节点的名称(最常见的是 'children',这里是 'layers',但我见过很多其他的.)返回的函数接受一个谓词并返回另一个接受数组的函数,并且递归地只保留谓词返回 true 的那些节点.

使用它,我们可以通过将 'layers' 与检查节点的 的谓词一起传递给 deepFilter 来编写 removeByIdid 无法匹配我们的目标.看起来像这样

const deepFilter = (childProp) =>(预测) =>(xs) =>xs .flatMap (({[childProp]: children = [], ...rest}) =>预(休息)?[{...rest, [childProp]: deepFilter (childProp) (pred) (children)}]: [])const removeById = (目标) =>deepFilter ('layers') (({id}) => id !== target)const payload = [{id: 1, name: "Shrek", lock: false, checked: false, selected: false, layers: [/* onions has layers */]}, {id: 2, name: "Fiona",锁定:假,选中:假,选中:假,层:[{id:4,名称:法夸德勋爵",锁定:假,选中:假,选中:假,层:[{id:5,名称:《白马王子》,锁:假,选中:假,选中:假,图层:[]}]}]},{id:3,名字:驴",锁:假,选中:假,选中:假,层:[/* 冻糕有层 */]}]控制台 .log (removeById (5)(有效负载))

.as-console-wrapper {max-height: 100% !important;顶部:0}

如果我们更喜欢这样调用:removeById(payload, 5),那么我们可以简单地写

const removeById = (payload, target) =>deepFilter ('layers') (({id}) => id !== target) (payload)

这里的一大优势是我们可以以简单的方式编写一个可重用的函数,并为它找到无处不在的用途,使我们的自定义代码变得非常简单.

I'm trying to deep filter until specific object with id found. I've taken these references,

  1. Recursively filter array of objects
  2. Filter items in array of objects
  3. Recursively filter array of objects with different properties
  4. Remove Object from Array using JavaScript

I am able to find the parent node, But was unable to delete specific children. What I'm doing wrong here?

Payload,

[
  {
    id: 1,
    name: "Shrek",
    lock: false,
    checked: false,
    selected: false,
    layers: [],
  },
  {
    id: 2,
    name: "Fiona",
    lock: false,
    checked: false,
    selected: false,
    layers: [
      {
        id: 4,
        name: "Lord Farquad",
        lock: false,
        checked: false,
        selected: false,
        layers: [
          {
            id: 5,
            name: "Prince Charming",
            lock: false,
            checked: false,
            selected: false,
            layers: [],
          },
        ],
      },
    ],
  },
  {
    id: 3,
    name: "Donkey",
    lock: false,
    checked: false,
    selected: false,
    layers: [],
  },
]

I'm getting Parent node with this code, but not sure from where to splice.

this.layers.filter(function f(o: any) {
  if (o.id == 5) return true;
  if (o.layers) return (o.layers = o.layers.filter(f)).length;
});

Expecting Output:

[
  {
    id: 1,
    name: "Shrek",
    lock: false,
    checked: false,
    selected: false,
    layers: [],
  },
  {
    id: 2,
    name: "Fiona",
    lock: false,
    checked: false,
    selected: false,
    layers: [
      {
        id: 4,
        name: "Lord Farquad",
        lock: false,
        checked: false,
        selected: false,
        layers: [],
      },
    ],
  },
  {
    id: 3,
    name: "Donkey",
    lock: false,
    checked: false,
    selected: false,
    layers: [],
  },
]

解决方案

I would try to build this on top of a reusable function. I abstracted a deepFilter from another answer so that we can configure the name of the child nodes (most commonly 'children', here 'layers', but I've seen many others.) The returned function takes a predicate and returns another function which takes an array, and recursively keeps only those nodes for which the predicate returns true.

Using this, we can write removeById by passing 'layers' to deepFilter along with a predicate that checks if a node's id fails to match our target. It looks like this

const deepFilter = (childProp) => (pred) => (xs) =>
  xs .flatMap (({[childProp]: children = [], ...rest}) => 
    pred (rest)
      ? [{... rest, [childProp]: deepFilter (childProp) (pred) (children)}]
      : []
  )

const removeById = (target) => 
  deepFilter ('layers') (({id}) => id !== target)

const payload = [{id: 1, name: "Shrek", lock: false, checked: false, selected: false, layers: [/* onions have layers */]}, {id: 2, name: "Fiona", lock: false, checked: false, selected: false, layers: [{id: 4, name: "Lord Farquad", lock: false, checked: false, selected: false, layers: [{id: 5, name: "Prince Charming", lock: false, checked: false, selected: false, layers: []}]}]}, {id: 3, name: "Donkey", lock: false, checked: false, selected: false, layers: [/* parfaits have layers */]}]

console .log (
  removeById (5) (payload)
)

.as-console-wrapper {max-height: 100% !important; top: 0}

If we prefer to call in this manner: removeById (payload, 5), then we can simply write

const removeById = (payload, target) => 
  deepFilter ('layers') (({id}) => id !== target) (payload)

The big advantage here is that we can write a reusable function in a simple manner, and find uses all over the place for it, making our custom code extremely trivial.

这篇关于递归过滤和删除对象数组中的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆