Home > Software design >  Function similar to _.get from lodash but that goes over all items in an array instead of specified
Function similar to _.get from lodash but that goes over all items in an array instead of specified

Time:11-04

I am trying to achieve a similar behavior to lodash's _.get() but with the difference that the function will be able to go over all/any of the arrays in the path instead of specifying the index in the path (ie. 'abc.xyz[0])


    // Example 1
    
    const _object = {abc: {xyz: [{value: 1}, {value: 2}]}};
    
    console.log(accumulateValues(_object, 'abc.xyz.value');
    // Desired output: [{value: 1}, {value: 2}]
    
    // Example 2
    
    const _object = {abc: [{xyz: [{values: 1}]}]};
    
    console.log(accumulateValues(_object, 'abc.xyz.values');
    // Desired output: [1]

CodePudding user response:

A fairly simple approach, if you want [1, 2] out of that might look like this:

const query = (path, ps = path .split ('.')) => (obj) =>
  ps .reduce ((a, p) => a .flatMap (x => (x || {}) [p]) .filter (Boolean), [obj])

const _object = {abc: [{xyz: [{value: 1}, {value: 2}]}]}

console .log (query ('abc.xyz.value') (_object))
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

If you're looking for [{value: 1}, {value: 2}], it probably wouldn't be much harder. But if somehow, as the question seems to imply, you want either result, based upon how you wrap 'abc', then I don't really understand your requirements.

Here the brackets surrounding some nodes (such as [xyz]) don't add any value, since we simply assume there is an array all the way down, wrapping the initial value in one. If you still wanted to supply them, we could remove them before processing:

const query = (path, ps = path .replace (/[\[\]]/g, '') .split ('.')) => (obj) =>
// ...

We might want to improve this to take arrays at the root by checking whether the input was an array already before wrapping it in one. I leave that as an exercise.

  • Related