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

[solved] filterDeep without the nested path #70

Closed kissu closed 4 years ago

kissu commented 4 years ago

Hi ! πŸ‘‹πŸ» Thanks you for the awesome package. πŸ™πŸ»

I'm asking for some help. Especially the filterDeep method.

I do currently have an object like this

{
  "a": {
    "b": {
      "c": {
      ...,
      "nestedItem": {
        "matchMe": true,
        "name": "cool name",
        "url": "https://"
      },
      ...,
      }
    }
  }
}

and I'm filtering by, let's say matchMe. I want to get the property and all the others at the same level (my wished result is not nested).

The issue is that I do have to access that kind of structure: a.b.c.nestedItem but I do wish to have only the object

{
  "matchMe": true,
  "name": "cool name",
  "url": "https://"
}

Basically what a findDeep returns. ☺️

I tried various options like includeRoot, rootIsChildren etc...but none was successful. 😞

YuriGor commented 4 years ago

Hi, thank you! Could you please give me a valid source JSON and expected result JSON, then I will give you a working example. Now, if I got your question correctly, I can suggest to use

let res = _.findValueDeep(sourceData, 'matchMe', {leavesOnly:false});

example here

YuriGor commented 4 years ago

No feedback, closing for now, let me know if you still have some questions.

kissu commented 4 years ago

Hey ! Sorry for the late response (lost 2 days on some damn plumbing πŸ˜† πŸ’§ ...). πŸ™€ Sorry also for not being precise enough on my question.

So, I basically wanted to have a filter but to have an object or a whole array at the end, without the whole path to the object, just the object. So basically a filterDeep + findDeep at the same time.

Then I saw #42 and realized that I could simply use reduceDeep to achieve what I was looking for.

So, I took my funky JSON and transformed into a JS object

fancyObject: {
  a: {
    amIaFruit: {
      matchMe: true,
      name: 'nice',
      url: 'https://www...',
    },
    b: {
      c: {
        d: {
          matchMe: false,
          name: 'super',
          url: 'https://www...',
        },
      },
    },
    d: {
      g: {
        h: {
          i: {
            j: {
              h: {
                matchMe: true,
                name: 'tasty',
                url: 'https://www...',
                children: {
                  matchMe: true,
                  name: 'santa',
                  url: 'https://www...',
                },
              },
            },
          },
        },
        matchMe: true,
        name: 'penguin',
        url: 'https//www...',
      },
    },
  },
}

Then I used the reducer, simply and totally flexible with parent if needed !

const filtered = reduceDeep(
  this.fancyObject,
  (acc, value, key, parent) => {
    if (key === 'matchMe' && value) acc.push(parent)
    return acc
  },
  [],
  { leavesOnly: true } // not sure if this is actually needed, can't see difference
)

And here we are, a totally clean payload to use on the frontend ! πŸ˜ƒ

[{
  "amIaFruit": {
    "matchMe": true,
    "name": "nice",
    "url": "https://www..."
},
{
  "matchMe": true,
  "name": "tasty",
  "url": "https://www..."
},
{
  "matchMe": true,
  "name": "santa",
  "url": "https://www..."
},
{
  "matchMe": true,
  "name": "penguin",
  "url": "https//www..."
}]

Posted this here, if somebody ever needs it someday. Thanks again for your work Yuri ! πŸ™πŸ»

YuriGor commented 4 years ago

Ok, got it, so you actually wanted selectDeep which is not implemented yet :) so yes, your solution is most optimal currently.

kissu commented 4 years ago

Yeah, that's what I saw but still managed to do it in a clean way. ❀️