0

I'm getting to grips with using functional programming beyond a simple map or two. I have a situation where I want to be able to filter some elements from an array of objects, based on a particular field of those objects. It's a contrived example, but here goes:

I have a list of field definitions, and I want to extract two of them based on their title.

const toSearch = [
  { title: "name", description: "Their name" },
  { title: "age", description: "Their age" },
  { title: "gender", description: "Their gender" }
]

const fieldsToFind = ["name", "age"]
let filterObjects = R.map(R.objOf('title'), fieldsToFind)
let filterFuncs = R.map(R.whereEq(R.__), filterObjects)
let found = R.map(R.filter, filterFuncs)

console.log("Filter objects:", JSON.stringify(filterObjects))
console.log("Filter functions:", JSON.stringify(filterFuncs))

console.log("Found:", found[0](toSearch))
console.log("Found:", found[1](toSearch))

If I run this, the last of the output is the two elements of toSearch that I'm looking for, but it's not exactly neat. I've been trying to get another map working to get around executing found elements manually, but I also feel that even leading up to that point I'm taking an overly circuitous route.

Although it's a contrived example, is there a neater way of accomplishing this in a functional style?

chooban
  • 9,018
  • 2
  • 20
  • 36

3 Answers3

2

One fairly simple way of doing this is:

R.filter(R.where({R.title: R.contains(R.__, ['name', 'age'])}))(toSearch);
//=> [
//     {"description": "Their name", "title": "name"}, 
//     {"description": "Their age", "title": "age"}
//   ]

or, equivalently,

R.filter(R.where({title: R.flip(R.contains)(['name', 'age'])}))(toSearch);

One advantage, especially if you import the relevant functions from R into your scope, is how closely this reads to your problem domain:

var myFunc = filter(where({title: contains(__, ['name', 'age'])}));

myFunc = filter where the title contains 'name' or 'age'.

You can see this in action on the Ramda REPL.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
0

You could use .reduce to accomplish your task. MDN has a very brief explanation of the reduce function

Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
Martin Schmid
  • 279
  • 3
  • 6
0

I have a situation where I want to be able to filter some elements from an array of objects, based on a particular field of those objects.

For your situation, its quite simple

var filteredItems = toSearch.filter(function(value){ return fieldsToFind.indexOf(value.title) != -1 });
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • 1
    Yeah, that's definitely the sensible way to go. In a way I'm trying to find an overly complicated solution to this just to get some insight into chaining the functions together. – chooban Mar 11 '16 at 12:14