0
[{"code":"96","value":"RemoveTest","parentLabelCode":1,"color":null,"level":1,"children":[{"code":"97","value":"R1","parentLabelCode":96,"color":null,"level":2,"children":[],"visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":1,"labelTranslations":null},{"code":"98","value":"R2","parentLabelCode":96,"color":null,"level":2,"children":[],"visible":true,"retired":true,"systemLabel":true,"removeOnArchive":true,"displayNumber":2,"labelTranslations":null},{"code":"99","value":"R3","parentLabelCode":96,"color":null,"level":2,"children":[],"visible":true,"retired":true,"systemLabel":true,"removeOnArchive":true,"displayNumber":2,"labelTranslations":null}],"visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":0,"labelTranslations":null}]

I want this output: Filter based on retired:false, retired : true , should not be display and have multiple object and have deep nested children i am doing recursively but not getting expected output

 var list = label_lists.filter(function f(item) {
            return item.retired==false ||
            item.children && (item.children = item.children.filter(f)).length
          })

[{"code":"96","value":"RemoveTest","parentLabelCode":1,"color":null,"level":1,"children":[{"code":"97","value":"R1","parentLabelCode":96,"color":null,"level":2,"children":[],"visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":1,"labelTranslations":null}],"visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":0,"labelTranslations":null}]

2 Answers2

1

Here's a recursive solution, which also copies rather than modifies the source objects:

function notRetired(arr) {
    return arr.filter(item => !item.retired)
        .map(item => Object.assign({}, item, {
            children: notRetired(item.children)
        }));
}

Here's a (slightly hacky) variant which works with cyclical structures:

function notRetired(arr, cache = null) {
    return arr.filter(item => !item.retired)
        .map((item, ret) => (cache || (cache = new Map())).get(item) ||
            (cache.set(item, ret = {}) && Object.assign(ret, item, {
                children: notRetired(item.children, cache)
            })));
}
Mike D Sutton
  • 716
  • 3
  • 9
  • __Good:__ I did not see the `having the same nested property`. Apparently the op do not care about active children of retired people. As he says `retired : true , should not be display`. – Tinmarino Mar 19 '20 at 14:12
  • Uncaught RangeError: Maximum call stack size exceeded is coming – Rahul Panwar Mar 20 '20 at 03:47
  • Sounds like you may have a cyclical structure, how is your source data array built? Possibly better to filter at the point the data structure is created instead, although there are ways of mitigating stack overflows in recursive functions if that's not feasible. – Mike D Sutton Mar 20 '20 at 09:44
0

You are filtering people that : are not retired (item.retired==false) or (||) have children (item.children) and (&&) whose children are all not retired (item.children = item.children.filter(f)).length)

I think you want for all people include children give me all the non retired. Is that correct ?

var label_lists = [{
    "code":"96","value":"RemoveTest","parentLabelCode":1,"color":null,"level":1,
    "children":[{
        "code":"97","value":"R1","parentLabelCode":96,"color":null,"level":2,"children":[],"visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":1,"labelTranslations":null
    }],
    "visible":true,"retired":false,"systemLabel":true,"removeOnArchive":true,"displayNumber":0,"labelTranslations":null}];

function filterActive(dic) {
    return dic.retired==false ? dic : [];
}

function findAll(array) {
    var res = [];
    for (item of array) {
        res.push(filterActive(item));
        res = res.concat(findAll(item.children));
    }
    return res;
}

console.log(findAll(label_lists));

--->

[ { code: '96',
    value: 'RemoveTest',
    parentLabelCode: 1,
    color: null,
    level: 1,
    children: [ [Object] ],
    visible: true,
    retired: false,
    systemLabel: true,
    removeOnArchive: true,
    displayNumber: 0,
    labelTranslations: null },
  { code: '97',
    value: 'R1',
    parentLabelCode: 96,
    color: null,
    level: 2,
    children: [],
    visible: true,
    retired: false,
    systemLabel: true,
    removeOnArchive: true,
    displayNumber: 1,
    labelTranslations: null } ]

Note on functional programming. Your intent is indeed pretty good. But from your question you want to change the structure of the list. Note that filter can only decrease the list size in any case. reduce is the laser sword for your case.

First write it as loop and functions, then any loop on array can be changed to map, filter or reduce.

Welcome to SO by the way !

Tinmarino
  • 3,693
  • 24
  • 33
  • Hi @tinmarino this is giving all children as a blank if has retired:false do not need that either it has true or false, and in parent array it has all children only need children which has retired: false, need to pop out you can see my input and output – Rahul Panwar Mar 20 '20 at 04:02
  • Basically need to pop not the filter – Rahul Panwar Mar 20 '20 at 04:18
  • Yes and it flattens the list. Mike solution is better you must increase stack size. https://stackoverflow.com/questions/20936486/node-js-maximum-call-stack-size-exceeded – Tinmarino Mar 20 '20 at 05:40