Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get all values from a nested array #13

Closed
ecdeveloper opened this issue Mar 5, 2015 · 5 comments
Closed

Get all values from a nested array #13

ecdeveloper opened this issue Mar 5, 2015 · 5 comments
Labels

Comments

@ecdeveloper
Copy link

Hey,

It would be really great if I could get a range of values from a nested array. So assume I have an object which looks like this:

{
    prop1: {
        prop2: [
            { prop3: 'abc' },
            { prop3: 'def' }
        ]
    }
}

I can get them now by calling:

selectn('prop1.prop2[0].prop3', obj);
selectn('prop1.prop2[1].prop3', obj);

But it would be handy to use something like:

selectn('prop1.prop2[].prop3', obj);
or
selectn('prop1.prop2[*].prop3', obj);

Is that doable somehow?

Thanks

@wilmoore
Copy link
Owner

wilmoore commented Mar 5, 2015

Is that doable somehow?

Yes, this is doable. I wrote up a prototype and while it works, I wasn't satisfied with the potential for edge cases. For example:

var data = {
  people: [
    { name: '', age: 27 },
    { name: '', age: 35 },
    { name: '', age: 18 },
    { name: '', age: 21 }
  ]
};

If we use the proposed syntax, it would be something like:

selectn("people[*].age")
//=> [ 27, 35, 18, 21 ]

This works fine; however, things start to get weird with the following structure:

var data = {
  people: [
    { name: '', about: { age: 27 } },
    { name: '', about: { age: 35 } },
    { name: '', about: { age: 18 } },
    { name: '', about: { age: 21 } }
  ]
};

One would expect the following to work:

selectn("people[*].about.age")
//=> undefined

The problem is that instead of plucking about.age we are actually saying, pluck about, then get the age index from the resulting array.

One way to correct this is to ensure that anytime we see the special *, we concatenate the rest of the path elements and do a deep pluck (i.e. in the above above, this would be about.age). This would absolutely work; however, when you consider we've increased the LOC by almost 1/3 and added to the scope of the module by special casing the * manipulating the path, I have to think, it isn't worth it.

Besides, it's quite compose-able as-is if you consider the following example:

var data = {
  people: [
    { name: '', about: { age: 27 } },
    { name: '', about: { age: 35 } },
    { name: '', about: { age: 18 } },
    { name: '', about: { age: 21 } }
  ]
};

var ages = selectn("people", data).map(selectn("about.age"));
//=> [ 27, 35, 18, 21 ]

or if you know for sure data.people exists:

var ages = data.people.map(selectn("about.age"));
//=> [ 27, 35, 18, 21 ]

If not in an ES5 environment, you can use a shim for .map or you can use the underscore or lodash libs.

@mavarazy
Copy link

mavarazy commented Jul 6, 2017

Wonder if you reconsider fixing this since selectn is used in https://github.com/CacheControl/json-rules-engine

We have following use case

let obj = {
    medications: [
      { type: "A" },
      { type: "B" },
      { type: "C" }
    ]
  };

And we need an event triggered if type is one of "A", "C", but

selectn("medications.type", obj)

would return undefined instead of an array of A, B, C

@wilmoore
Copy link
Owner

wilmoore commented Jul 6, 2017

@mavarazy - Given you are expecting a list (array) back, you might be looking for this instead: https://www.npmjs.com/package/array-mapcat

var mapcat = require('array-mapcat')

let obj = {
    medications: [
      { type: "A" },
      { type: "B" },
      { type: "C" }
    ]
}

mapcat('type', obj.medications)
//=> ['A', 'B', 'C'] 

@wilmoore
Copy link
Owner

wilmoore commented Jul 6, 2017

@mavarazy Definitely let me know if that does or doesn't work for you or if we need to figure out some other solution.

@mavarazy
Copy link

mavarazy commented Jul 6, 2017

Thanks. I worked around that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants