11

I'm trying to accomplish this in a functional manner (with Ramda). My JSON is structured like this

[
    {username: 'bob', age: 30, tags: ['work', 'boring']},
    {username: 'jim', age: 25, tags: ['home', 'fun']},
    {username: 'jane', age: 30, tags: ['vacation', 'fun']}
]

and I am trying to filter based on a value in the 'tags' property, but have not been successful. I am able to filter on ints/strings (age and username), but I can't figure out how to do so with values in nested arrays (tags). Any help would be much appreciated.

user3783301
  • 143
  • 1
  • 1
  • 4

3 Answers3

24

There are many ways you could do this. But I think the cleanest one would be:

R.filter(R.where({tags: R.includes('fun')}))

You can see it in action in the Ramda REPL.

Other options, especially if the field is more deeply nested is to compose (or pipe) prop or path calls with contains or possibly to take advantage of lenses.

Still, I think the answer above is most readable.

Oscar
  • 1,250
  • 13
  • 19
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • that looks like a nice solution to me. And i like the way it reads: "filter where tags contains 'fun'" sounds very much like the problem description. – Buzz de Cafe Mar 25 '15 at 13:04
  • Thanks so much. Since posting I came up with this `var byTag = R.curry(function(tag, items) { var containsTag = function(val) { return R.contains(tag, val.tags); }; return R.filter(containsTag, items); });` but it's definitely not as pretty as your solution. For whatever reason using R.contains as the property value didn't even cross my mind. Thanks again! – user3783301 Mar 25 '15 at 13:13
  • I don't know if other libraries with similar `where` functions also allow a predicate in this place. We're pretty happy with this feature. – Scott Sauyet Mar 25 '15 at 13:27
  • I've just started to venture into functional programming and I must say, your library is pretty sweet so far. – user3783301 Mar 25 '15 at 13:32
  • Thanks. BTW, if you really wanted a points-free version of this, you could do something like this monstrosity: `var fn = R.useWith(R.filter, R.pipe(R.contains, R.createMapEntry('tags'), R.where), R.identity); fn('fun', data);`. But _why_?? It's much less readable. – Scott Sauyet Mar 25 '15 at 20:20
  • I altered the solution to access the username property, and it gave me an error `R.equals is not a function`. I don't understand why this won't work. __[REPL](http://ramdajs.com/repl/?v=0.13.0#?const%20data%20%3D%20%5B%0A%20%20%20%20%7Busername%3A%20%27bob%27%2C%20age%3A%2030%2C%20tags%3A%20%5B%27work%27%2C%20%27boring%27%5D%7D%2C%0A%20%20%20%20%7Busername%3A%20%27jane%27%2C%20age%3A%2030%2C%20tags%3A%20%5B%27vacation%27%2C%20%27fun%27%5D%7D%0A%5D%3B%0A%0AR.filter%28R.where%28%7Busername%3A%20R.equals%28%27jane%27%29%7D%29%29%28data%29%3B%0A)__ – garajo Jun 20 '17 at 18:52
  • 1
    @garajo: Your REPL URL points to v0.13 of Ramda. `equals` wasn't added until v0.15. – Scott Sauyet Jun 20 '17 at 19:15
3
const arr = [
 {username: 'bob', age: 30, tags: ['work', 'boring']},
 {username: 'jim', age: 25, tags: ['home', 'fun']},
 {username: 'jane', age: 30, tags: ['vacation', 'fun']}
];

res = R.filter(R.where({tags: R.contains('home')}), arr);
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
Zhang Yung
  • 46
  • 1
0
const arr = [
             {username: 'bob', age: 30, tags: ['work', 'boring']},
             {username: 'jim', age: 25, tags: ['home', 'fun']},
             {username: 'jane', age: 30, tags: ['vacation', 'fun']}
           ];
const filtTags = R.compose(R.filter, R.where({tags: R.includes('fun')})
const result = filtTags(arr)