【问题标题】:How to search filter in a tree-like structure?如何在树状结构中搜索过滤器?
【发布时间】:2021-06-29 00:56:14
【问题描述】:

我有一个应该过滤的树结构数据,结果应该保留树结构:

var tree = [
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 1"
            type: "Grandchild"
          },
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      },
      {
        text: "Child 2",
        type: "Child"
      }
    ]
  },
  {
    text: "Parent 2",
    type: "Parent"
  },
  {
    text: "Parent 3",
    type: "Parent"
  }
];

我想过滤树。我正在使用这种方法:

function filter(array, text) {
    return array.filter(function iter(o) {
        var temp;
        if (o.text === text) {
            return true;
        }
        if (!Array.isArray(o.nodes)) {
            return false;
        }
        temp = o.nodes.filter(iter);
        if (temp.length) {
            o.nodes = temp;
            return true;
        }
    });
}

它工作得很好。这个问题之前已经在Stack Overflow link 上提出过。

虽然,我有一个用例,如果 grandchild(仅在 grandchild 类型的情况下,而不是在 childparent 中)文本匹配,那么兄弟节点也应该与它们一起返回各自的父节点。答案可能很简单,但不知怎的,我想不出该怎么做。

所以如果我通过这个:Grandchild 2, 预期的输出应该是:

[
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 1"
            type: "Grandchild"
          },
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      }
    ]
  }
]

【问题讨论】:

    标签: javascript


    【解决方案1】:

    如果想要的对象在数组中,您可以通过 ching 采用非变异方法,然后从数组中获取所有项目,否则获取下一级并添加对象,如果孩子在下一级。

    function filter(array, key, value) {
        return array.some(o => o[key] === value && o.type === 'Grandchild')
            ? array
            : array.reduce((r, o) => {
                if (o[key] === value) return [...r, o];
                if (o.nodes) {
                    const nodes = filter(o.nodes, key, value);
                    if (nodes.length) r.push({ ...o, nodes });
                }
                return r;
            }, []);
    }
    
    var tree = [{ text: "Parent 1", nodes: [{ text: "Child 1", type: "Child", nodes: [{ text: "Grandchild 1", type: "Grandchild" }, { text: "Grandchild 2", type: "Grandchild" }] }, { text: "Child 2", type: "Child" }] }, { text: "Parent 2", type: "Parent" }, { text: "Parent 3", type: "Parent" }];
    
    console.log(filter(tree, 'text', 'Grandchild 2'));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 嗨@NinaScholz,对不起,这是延迟的。我在问题本身中已经提到,只有在Grandchild类型的情况下才应该返回所有兄弟节点。但在答案中,如果我提供 Parent 1 所有对象都将被返回。你能看看这个。谢谢!
    【解决方案2】:

    首先将帮助方法写入find 包含已给出大子文本条件的对象,然后使用节点上的过滤器更新找到的对象。

    const filter = (data, word) => {
      const criteria = x => x.nodes?.find(({ text }) => text === word);
      const found = data.find(item => {
        if (!item.nodes) {
          return false;
        }
        return item.nodes.find(criteria);
      });
      return found ? [{ ...found, nodes: found.nodes.filter(criteria) }] : null;
    };
    
    var tree = [
      {
        text: "Parent 1",
        nodes: [
          {
            text: "Child 1",
            type: "Child",
            nodes: [
              {
                text: "Grandchild 1",
                type: "Grandchild"
              },
              {
                text: "Grandchild 2",
                type: "Grandchild"
              }
            ]
          },
          {
            text: "Child 2",
            type: "Child"
          }
        ]
      },
      {
        text: "Parent 2",
        type: "Parent"
      },
      {
        text: "Parent 3",
        type: "Parent"
      }
    ];
    
    console.log(filter(tree, "Grandchild 2"));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 2020-04-07
      • 2013-12-29
      相关资源
      最近更新 更多