Search code examples
javascriptramda.jsdestructuring

Ramda function that takes in list of paths and returns a function that destructures an object


Hello can anyone point me to the right direction with this problem that I have,

Basically I have a function that takes in an object and destructures them.

({ data: { accounts, loading } }) => ({
  accounts,
  loading,
})

I would like to make a ramda function that takes in a list of paths, deeply extracts the value from the object and returns an object out of it.

Achieving the same functionality above, I'd like to use the function like this:

deepExtract(['data.accounts', 'data.loading'])
// input: { data: { accounts: 1, loading: 1 } }
// output: { accounts: 1, loading: 1 } (notice the keys doesn't have `data` in it.)

Current progress:

R.pipe(
  R.map(R.split('.')), // <-- gives me a list that I can feed into lensPath [['data', 'accounts'], ['data', 'loading']
  /*  Can't figure out next steps but I'd like to run each of the list to:
   *  1. lensProp
   *  2. merge
   */
)(['data.accounts', 'data.loading'])

Solution

  • Here is a fairly simple version without your additional split-on-: requirement:

    const deepExtract = curry((paths, obj) => {
      const fullPaths = map(split('.'), paths)
      const names = map(last, fullPaths)
      const vals = map(flip(path)(obj), fullPaths)
      return zipObj(names, vals)
    })
    

    While we could probably make this point-free, it is quite readable like this, and likely wouldn't be in a point-free version.


    Update

    Adding the : rule makes for less pleasant code:

    const deepExtract = curry((paths, obj) => {
      const namedPaths = map(split(':'), paths)
      const fullPaths = map(pipe(head, split('.')), namedPaths)
      const names = map(ifElse(nth(1), nth(1),  pipe(head, split('.'), last)), namedPaths)
      const vals = map(flip(path)(obj), fullPaths)
      return zipObj(names, vals)
    })
    

    I haven't thought hard about how to avoid the duplication with split('.'). It probably can be done without too much difficulty. But this is unlikely to be a serious performance hit, only an issue of pretty code.