0

I have a list which could look like this:

let list = [
  {
    name: "Level 1",
    children: [
      {
        name: "Level 2",
        children: [
          {
            name: "Level 3A",
            children: [],
          },
          {
            name: "Level 3B",
            children: [],
          },
          {
            name: "Level 3C",
            children: [],
          },
        ],
      },
    ],
  },
];

As you can see it consists of elements with 2 properties: name and children. This is simple list but it can be nested many levels down and each element could have a lot of children.

Moreover i have sample array of arrays of strings like this:

const filterRows = [
    ["Level 1", "Level 2", "Level 3A"],
    ["level 1", "Level 2", "Level 3C"]
]

Each of this 2 arrays of strings represents each 'row' in my list. (Here we don't have ["level 1", "Level 2", "Level 3B"])

My goal is to make something like filter. So based on filterRows i want my list to be:

let filteredList = [
    {
      name: "Level 1",
      children: [
        {
          name: "Level 2",
          children: [
            {
              name: "Level 3A",
              children: [],
            },
            {
              name: "Level 3C",
              children: [],
            },
          ],
        },
      ],
    },
  ];

As you can see in filteredList we only have rows specified in filterRows (so here we don't have "Level 3B")

Could you help me create function to do that?

As i said list (initial list) could be much more complicated I simplify it. Also filterRows can be different (but always correctly represent some rows in our list). So it cannot be hardcoded.

1
  • 1
    Please share what you've tried so far. Any progress? Commented Apr 8, 2021 at 19:32

1 Answer 1

2

With matching strings, you could build a tree and rebuild the structure with the wanted items.

const
    filter = level => (r, { name, children }) => {
        const next = level[name];
        if (next) {
            if (Object.keys(next).length) children = children.reduce(filter(next), []);
            r.push({ name, children });
        }
        return r;
    },
    list = [{ name: "Level 1", children: [{ name: "Level 2", children: [{ name: "Level 3A", children: [] }, { name: "Level 3B", children: [] }, { name: "Level 3C", children: [] }] }] }],
    filterRows =  [["Level 1", "Level 2", "Level 3A"], ["Level 1", "Level 2", "Level 3C"]],
    tree = filterRows.reduce((r, a) => {
        a.reduce((o, k) => o[k] ??= {}, r);
        return r;
    }, {}),
    result = list.reduce(filter(tree), []);

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

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

1 Comment

works almost fine, when we have e.g. ["Level 1"] in filterRows it should return all nested elements in "Level 1". Now it returns only "Level 1", but it not returns all its children. Could you change it? Thank you in advance

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.