YuriGor / deepdash

eachDeep, filterDeep, findDeep, someDeep, omitDeep, pickDeep, keysDeep etc.. Tree traversal library written in Underscore/Lodash fashion
https://deepdash.io/
MIT License
274 stars 12 forks source link

omitDeep with function? #62

Closed muuvmuuv closed 3 years ago

muuvmuuv commented 4 years ago

Is it possible to use a function in omitDeep? I would like to exclude an item and its children from an array but only if the id of an item matches. Please correct me if this isn't the correct function for this but with filterDeep I got an infinite loop (idk why).

This is what I expect:

omitDeep(
      items,
      (value) => {
          return value.id === itemId
      },
      {
          childrenPath: ['children'],
      }
 )

PS: Thanks for the great lib. This is a huge time saver for me in my current project.

YuriGor commented 4 years ago

Hi, the only way I know to have infinite loop is to have circular references in your data - in this case, you need to enable checkCircular option. If it's not the case then you found a bug, please share how to reproduce it.

Here is an example similar to what you need: https://codepen.io/yurigor/pen/qBbbXxY?editors=0010

You can fork this pen, put your data and check if it's working for you. But please share how did you got infinite loop.

muuvmuuv commented 4 years ago

Here is a reproducible example: https://stackblitz.com/edit/angular-ivy-b8uhnv?file=src%2Fapp%2Fhello.component.ts

I found out that there is a circular references inside self. Can I exclude this key explicitly?

YuriGor commented 4 years ago

So if it's a circular ref then no bug here just enable circular check. To exclude check keepCircular or replaceCircularBy filterDeep options

YuriGor commented 4 years ago

As I see in your example - adding checkCircular:true helps But it still looks strange for me why this 'self' property visited if childrenPath option specified, So I will need to check it. dump code here to not loose it if you will update your example:

var data = [
  {
    "id": "dh8ge0",
    "name": "Long it takes",
    "type": "distance",
    "self": this,
    "value": 2
  },
  {
    "id": "z765tghj",
    "name": "Capability 01",
    "type": "checkbox",
    "state": "active",
    "self": "COMPONENT",
    "changed": {
      "_isScalar": false,
      "observers": [],
      "closed": false,
      "isStopped": false,
      "hasError": false,
      "thrownError": null,
      "__isAsync": false
    }
  },
  {
    "id": "fh390hdas",
    "name": "Wildy",
    "self": "COMPONENT",
    "type": "wildcard"
  }
]

    console.clear()
    console.log(data)
    const newData = filterDeep(data, node => node.id !== 'z765tghj', {
      checkCircular: true,
      childrenPath: ['children'], 
      onFalse:{skipChildren:true}}
    );
    console.log(newData);
YuriGor commented 4 years ago

Ok, found, we need to checkCircular in filterDeep in case of childrenPath is specified and circular reference is not one of some children because of condensing. Bu default filterDeep result is deeply condensed, and condenseDeep method does not support 'childrenPath' option, so it will go over all the properties. So it's not a bug, but kind of inefficiency I will improve this in a separate task.

muuvmuuv commented 4 years ago

Just for ur information I got it working by getting rid of the circular dependency which should not be there so thanks for giving me this hint.

This is my final solution:

      const newList: ZoneItem[] =
        filterDeep(
          this.zones[index].items,
          (value: ZoneItem): boolean => {
            return value.id !== itemId
          },
          {
            childrenPath: ['children'],
            onFalse: { skipChildren: true },
          }
        ) || []
YuriGor commented 4 years ago

Yeah, looks good. If you can avoid circular refs - better to do it, because checking for circular references in filterDeep impacts performance.