0

I have a list, which contains items such as this: [{name:...}, {name:...}], ...

I would like to extract only those elements, where name matches to any in a set of regular expressions.

I was able to do it like so:

const cards = yield ... //Network request to get my list of items
const matchers = [/^Remaining Space:/, /^Remaining Weight:/, /^Gross:/];
const propTester = (prop, pred) => R.pipe(R.prop(prop), R.test(pred));
const extractors = R.ap([propTester('name')], matchers);
const [ spaceCard, weightCard, grossCard ] = 
    R.ap(R.ap([R.find], extractors), [cards]);

Is there any way to simplify that?

Vasili Sviridov
  • 191
  • 2
  • 4
  • 14

1 Answers1

0

Here's one possibility:

const matchers = [/^Remaining Space:/, /^Remaining Weight:/, /^Gross:/];
const testers = R.map(pred => R.pipe(R.prop('name'), R.test(pred)), matchers);
const extractors = R.map(R.find, testers)
const [ spaceCard, weightCard, grossCard ] = R.juxt(extractors)(cards);

It assumes that 'name' is fixed and you don't need to be able to change it dynamically. If you do, it would be slightly more work. The main point is the use of R.juxt, which "applies a list of functions to a list of values."

If we tried really hard, we could probably make testers points-free as well, but threading all that through the whole thing to make a single function from matchers and cards to your results, while possible, would likely read to less readable code.

You can see this in action on the Ramda REPL.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • Thank you, Scott, an excellent answer as usual. I was really happy when I came with a slightly different problem solution on my own. It was to extract all possible properties from a list of objects with some nesting. ` const pertinentFields = ['listAfter.id', 'listBefore.id', 'list.id'];` ` const extractors = R.ap([R.pipe(R.split('.'), R.pathOr(null))], pertinentFields);` ` const ids = R.ap(extractors, [data]);` So I tried modelling the above problem on this one... – Vasili Sviridov Mar 18 '16 at 20:29