简体   繁体   中英

Search using ramda functions in object

I have the following code:

const trimString = (s) => s.trim()
const compareObjects = (o1, o2) => equals(o1, o2)
const itemExists = (haystack, needle) => contains(haystack, needle)

const objects = [
  { duration: '0.360000', name: 'Arthur', time: '0.660000',   paragraph: 'p0-0' },
  { duration: '0.150000', name: 'the',    time: '1.020000',   paragraph: 'p0-0' },
  { duration: '0.380000', name: 'rat',    time: '1.170000',   paragraph: 'p0-0' },
  { duration: '0.770000', name: '.',      time: '1.550000',   paragraph: 'p0-0' },
  { duration: '0.360000', name: 'Arthur', time: '89.820000',  paragraph: 'p1-0' },
  { duration: '0.390000', name: 'stood',  time: '90.180000',  paragraph: 'p1-0' },
  { duration: '0.090000', name: 'and',    time: '90.570000',  paragraph: 'p1-0' }
];

function searchFor(toSearch) {
  var results = [];
  toSearch = trimString(toSearch); // trim it
  for(var i=0; i<objects.length; i++) {
    for(var key in objects[i]) {
      if(objects[i][key].indexOf(toSearch)!=-1) {
        if(!itemExists(results, objects[i])) results.push(objects[i]);
      }
    }
  }
  return results;
}

log(searchFor('Arthur'))

I get the result:

[
    {
        duration: '0.360000',
        name: 'Arthur',
        time: '0.660000',
        paragraph: 'p0-0'
    },
    {
        duration: '0.360000',
        name: 'Arthur',
        time: '89.820000',
        paragraph: 'p1-0'
    }
]

But I am stuck on how to make this into a ramda function and able to add multiple search items and show the result only for p0-0 if I used Arthur the

Any advise is much appreciated.

What helps me when approaching a functional style is to build the full spec up slowly from the most basic requirements. The requirements aren't clear but it appears you want to return an the object which matches a name, and possibly extend this functionality so that you can pass in an array of names and get an array of objects back.

So let's start with the most basic requirement, which is to return a boolean based on if the name matches the given parameter. For this we'll use the function propEq :

const nameEq = pred => R.propEq('name', pred)

// This is just a partially application of:
// const nameEq = pred => obj => R.propEq('name', pred)(obj)

So now to find all objects in the list that match we use the function filter which will return the any elements which evaluate to true for the supplied function

const nameInList = pred => R.filter(nameEq(pred))

// This is again a partial application of:
// const nameInList = pred => obj => R.filter(nameEq(pred))(obj)

This can then be called with the

nameInList('Arthur')(objects)

which returns

[
  {
    "duration": "0.360000",
    "name": "Arthur",
    "paragraph": "p0-0",
    "time": "0.660000"
  },
  {
    "duration": "0.360000",
    "name": "Arthur",
    "paragraph": "p1-0",
    "time": "89.820000"
  }
]

or we can partially apply our function

const findArthur = nameInList('Arthur')

and later pass in our list of objects

findArthur(objects)

We can then go even further to reverse the parameters by defining:

const flipped = R.compose(R.curry, R.flip(R.uncurryN(2, nameInList)))

This will then allow us to partially apply the function to objects and simply lookup names by passing in a string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM