【问题标题】:FilrerDeep using deepdash keeping rollup verdictFilrerDeep 使用 deepdash 保持汇总判决
【发布时间】:2020-07-08 10:23:26
【问题描述】:

我想使用来自deepdash(任何其他解决方案也可以)的 filterDeep 来过滤下面的数据,以使判决汇总保持不变。

{
"diff": [
    {
        "actual": "parent1",
        "expected": "parent1",
        "match": true,
        "children": [
            {
                "actual": "child1",
                "expected": "child1",
                "match": true,
                "children": [
                    {
                        "actual": "grandchild1",
                        "expected": "grandchild1_NOT",
                        "match": true
                    }
                ]
            },
            {
                "actual": "child2",
                "expected": "child2",
                "match": true,
                "children": [
                    {
                        "actual": "C2_grandchild1",
                        "expected": "C2_grandchild1",
                        "match": true
                    },
                    {
                        "actual": "C2_grandchild2",
                        "expected": "C2_grandchild2_NOT",
                        "match": false
                    }
                ]
            }
        ]
    }
]

}

json的简单视图如下:

我想以这样一种方式过滤掉,因为 C2_grandchild2 失败(匹配:false),json 应该包含 parent1--> child2-->C2grandchild2。我试图通过显示其父层次结构来突出失败。所以 child1、grandchild1 和 C2_grandchild1 也不存在于过滤的 json 中

我已经尝试了示例here,但似乎无法很好地理解它以实现这一目标

PS:json 大部分时候都很大很深。

【问题讨论】:

    标签: javascript json reactjs lodash


    【解决方案1】:

    使用 deepdash 你会得到这样的结果:

    // data is your json
    const failed = _.filterDeep(data.diff,(v) => !v.match, {
      childrenPath:'children'
    });
    

    Here is a working example

    (v) => !v.match -- 这是过滤条件

    { childrenPath:'children' } -- 声明子属性名称的选项,使 deepdash 在“树模式”下工作

    如有任何问题,请联系我

    【讨论】:

    • 谢谢,效果很好。对以后的使用会很有用。我使用了@trincot 的答案
    【解决方案2】:

    您可以使用递归函数,它根据以下原则将节点数组映射到过滤后的数组:

    • 如果该节点有子节点,并且递归调用返回一个非空数组,则将一个新节点添加到具有这个减少的子节点数组的结果中
    • 如果节点没有子节点,或者递归调用返回一个空数组,则:
      • 如果节点有match: false,则将该节点原样添加到结果中
      • 否则,不要将此节点添加到结果中
    • 返回结果数组

    function filter(nodes) {
        return (nodes || []).map(node => {
            let { children, ...childlessNode} = node;
            children = filter(children);
            return children.length ? {...node, children } 
                                   : !node.match && childlessNode;
        }).filter(Boolean);
    }
    
    // Demo
    let data = {"diff": [{"actual": "parent1","expected": "parent1","match": true,"children": [{"actual": "child1","expected": "child1","match": true,"children": [{"actual": "grandchild1","expected": "grandchild1_NOT","match": true}]},{"actual": "child2","expected": "child2","match": true,"children": [{"actual": "C2_grandchild1","expected": "C2_grandchild1","match": true},{"actual": "C2_grandchild2","expected": "C2_grandchild2_NOT","match": false}]}]}]};
    let result = { diff: filter(data.diff) };
    console.log(result);

    这个 sn-p 输出相同的 diff 属性。如果您不需要该上层,则只需调用 filter(data.diff) 而无需将该结果包装到另一个对象中。

    说明

    (nodes || []) 的计算结果为 nodes,除非 nodes 不是数组,而是未定义。当使用node.children 调用函数时可能会发生这种情况,但node 确实具有children 属性。 JavaScript 允许引用不存在的属性,它只会评估对特殊值undefined 的引用。因此,如果此函数接收undefined 作为参数,它将使用空数组[] 继续表达式。否则.map 调用会触发异常。

    .map 将生成一个新数组,其元素数量与调用它的数组一样多。作为参数提供的回调函数将定义新数组为原始数组中的给定值获取的值(“映射”)。

    { children, ...childlessNode} = node; 会在一个children 变量中获得nodechildren 属性(或者undefinednode 没有这样的属性时),但更重要的是,它还会创建一个对象变量childlessNode 具有node 的所有其他 属性。

    filter(children):这是递归调用。如上所述,node 可能没有children 属性,但filter 函数处理得很好。它总是会返回一个数组。

    children.length ? ...... : .....: 三元运算符用于区分递归函数返回非空数组或返回空数组的情况。

    {...node, children }:这是一个简洁的语法,表示:创建一个新对象,它是node 的(浅)副本,但其children 属性应设置为children 变量。请注意,...spread syntax for object literals

    !node.match && childlessNode:如果node.match 为真,则!node.match 为假,并且&& 运算符短路使表达式false。这实际上意味着在此.map 调用中创建的数组可以包含false 值以及节点。请注意,JavaScript 允许这种类型的混合。如果!node.match 为假,则表达式的计算结果为childlessNode,这意味着此node 的映射只是节点本身,但没有子节点。

    .filter(Boolean):这将从.map 返回的数组中创建另一个数组。这次新数组中的值的数量可以更少。作为参数提供的回调函数将确定哪些值应该输入,哪些应该输出。 Boolean 是可用于此目的的本机函数。 Boolean(false) 只是 false,而 Boolean(any object)true。因此,这有效地返回了一个数组,其中删除了 false 值,只保留了节点对象。

    【讨论】:

    • 谢谢。我工作得很好。因为我更多来自核心java世界。我需要做更复杂的拟合,如果可以的话,如果你能多解释一点会很好,或者我会尝试运行多次并找出答案。不过非常感谢
    • 我添加了一些解释。
    • 非常感谢。真的很感激。
    • 很抱歉再次回来。多一点帮助。如果我使“Child1”的匹配:false,那么它应该删除 grandchild1 并且应该只显示 parent->child1,它不应该显示 grandchild1,因为它具有“match:true”
    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 2018-06-29
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    相关资源
    最近更新 更多