1

I have an array of unique values:

const array = [1, 2, 4]

I have a collection of unique objects:

const collection = [
  { type: 1, eyes: 'blue'},
  { type: 2, eyes: 'brown'},
  { type: 3, eyes: 'green'},
  { type: 4, eyes: 'blue'}
]

Using Ramda how do I extract all the objects from collection where type is included in array?

Expected outcome:

[
  { type: 1, eyes: 'blue'},
  { type: 2, eyes: 'brown'},
  { type: 4, eyes: 'blue'}
]
customcommander
  • 17,580
  • 5
  • 58
  • 84
Max Phillips
  • 6,991
  • 9
  • 44
  • 71
  • This is not ramda but you can define a filter function taking getter and compare function and compose multiple of these to create powerful array filters. Example [here](https://stackoverflow.com/a/50075368/1641941) – HMR May 03 '18 at 18:37

3 Answers3

4

Use R.innerJoin():

const array = [1, 2, 4]
const collection = [{ type: 1, eyes: 'blue'},{ type: 2, eyes: 'brown'}, { type: 3, eyes: 'green'}, { type: 4, eyes: 'blue'}]

const joinByType = R.innerJoin(
  (o, type) => o.type === type
)

const result = joinByType(collection, array)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

The same method in a more ramdaish way using R.propEq() to compare the type property with the type id from the array. We need to use R.flip() because innerJoin passes the object before the the value to compare to.

const array = [1, 2, 4]
const collection = [{ type: 1, eyes: 'blue'},{ type: 2, eyes: 'brown'}, { type: 3, eyes: 'green'}, { type: 4, eyes: 'blue'}]

const joinByType = R.innerJoin(R.flip(R.propEq('type')))

const result = joinByType(collection, array)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • 1
    if someone is missing the typescript types for innerJoin, just add this: declare module 'ramda' { interface Static { innerJoin(fn: (v: U, p: T) => boolean, x1: U[], x2: T[]): U[]; } } – Andreas Herd Nov 06 '18 at 12:05
  • How to get the missing items ? [ { type: 3, eyes: 'green'} ] – Nadhas Aug 15 '22 at 09:46
  • Reverse the condition - `const joinByType = R.innerJoin( (o, type) => o.type !== type )` (note the `!==`). – Ori Drori Aug 15 '22 at 09:55
1

Without ramda

collection.filter(item => array.includes(item.type))
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Mukesh Soni
  • 6,646
  • 3
  • 30
  • 37
1

I think the answer from Mukesh Soni is what you need for this. In Ramda, it might read filter(p => array.includes(p.type), collection), but that's much the same.

But Ramda is all about functions, and creating reusable and flexible functions to handle your needs. I would at least consider writing something like this:

const {curry, filter, contains, prop} = R

const collection = [{ type: 1, eyes: 'blue'},{ type: 2, eyes: 'brown'}, { type: 3, eyes: 'green'}, { type: 4, eyes: 'blue'}]
const array = [1, 2, 4]

const filterBy = curry((propName, selectedValues, collection) => 
  filter(e => contains(prop(propName, e), selectedValues), collection))

const newCollection = filterBy('type', array, collection)

console.log(newCollection)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

I might even go one step further, and allow for an arbitrary transformation function, rather than just prop:

const filterBy = curry((transform, selectedValues, collection) => 
  filter(e => selectedValues.includes(transform(e)), collection))

filterBy(prop('type'), array, collection)

But abstractions such as these are generally only helpful if you expect to make other use of them across your application. If this is the only place where you use a list of values to match with in order to filter a collection, then there is little reason for any reusable function.

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