4

To display correctly a Tree view in React, I need to filter a nested tree object.

I find this post : filter nested tree object without losing structure

But actually I would like to do the exactly opposite. For instance, if in my filterData function name === "a3" I would like to keep object with name === "a3"

const result = filterData(items, "a3")
const items = [
  {
    name: "a1",
    id: 1,
    children: [
      {
        name: "a2",
        id: 2,
        children: [
          {
            name: "a3",
            id: 3
          },
          {
            name: "a5",
            id: 4
          }
        ]
      }
    ]
  },
  {
    name: "b2",
    id: 2,
    children: [
      {
        name: "a2",
        id: 2,
        children: [
          {
            name: "a3",
            id: 3
          }
        ]
      },
      {
        name: "a4",
        id: 8
      }
    ]
  }
];
const result = [
  {
    name: "a1",
    id: 1,
    children: [
      {
        name: "a2",
        id: 2,
        children: [
          {
            name: "a3",
            id: 3
          }
        ]
      }
    ]
  },
  {
    name: "b2",
    id: 2,
    children: [
      {
        name: "a2",
        id: 2,
        children: [
          {
            name: "a3",
            id: 3
          }
        ]
      }
    ]
  }
];

2 Answers 2

6

You could create new objects without mutating the given data and reduce the arrays.

function filter(array, name) {
    return array.reduce((r, { children = [], ...o }) => {
        if (o.name === name) {
            r.push(o);
            return r;
        }
        children = filter(children, name);
        if (children.length) {
            r.push(Object.assign(o, { children }));
        }
        return r;
    }, []);
}    

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

console.log(filter(items, "a2"));
console.log(filter(items, "a3"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

3 Comments

Nina, once again You save my day ! it works perfectly, now I have to read and read again to be sure to understand your proposal ! Thanks a lot.
Thanks a lot, Actually, for instance for result = filter(items, "a2") it doesn't seem work, the under levels does not remove. I've tried to improve your code but I haven't find the solution yet... :( If we take the same items object than above, my result should be : javascript const result = [ { name: "a1", id: 1, children: [ { name: "a2", id: 2, } ] }, { name: "b2", id: 2, children: [ { name: "a2", id: 2, } ] } ];
i see, no children for found node, please see edit.
1

I've just improved the Nina's proposal in order to remove the under levels if "name" isn't include.

function filter(array, name) {
  return array.reduce((r, o) => {
    var children;
    children = filter(o.children || [], name);

    if (children.length) {
      r.push(Object.assign({}, o, { children }));
    }

    if (o.name === name) {
      r.push(o);
      if (o.children && o.children.name !== name) {
        r[0].children = [];
      }
    }

    return r;
  }, []);
}

var items = [{ name: "a1", id: 1, children: [{ name: "a2", id: 2, children: [{ name: "a3", id: 3 }, { name: "a5", id: 4 }] }] }, { name: "b2", id: 2, children: [{ name: "a2", id: 2, children: [{ name: "a3", id: 3 }] }, { name: "a4", id: 8 }] }],

result = filter(items, "a2");

console.log(result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.