javascriptarraysfilterramda.js

Filter two lists against each other using predicate with ramda


I have an array of rooms, each of which contain another array of disabledDays in which they cannot be booked for:

const rooms = [
  {
    disabledDays: [],
    title: 'roomOne'
  },
  {
    disabledDays: ['2019-07-10T01:00:00.000Z'],
    title: 'roomTwo'
  },
  {
    disabledDays: [
      '2019-07-08T01:00:00.000Z',
      '2019-07-09T01:00:00.000Z',
      '2019-07-02T01:00:00.000Z'
    ],
    title: 'roomThree'
  },
  {
    disabledDays: [],
    title: 'roomFour'
  }
];

I then also have a range of chosen dates which I would like to use to find available rooms for:

const selectedDates = [
  '2019-07-06T01:00:00.000Z',
  '2019-07-07T01:00:00.000Z',
  '2019-07-08T01:00:00.000Z',
  '2019-07-09T01:00:00.000Z'
];

In this case I want to find rooms that have none of the selectedDates in their disabledDays array.

My attempt so far uses a combination of map, reject and any, however this doesn’t seem to return the full room as a result.

const result = map(
  room => reject(
    date => any(disabled => isSameDay(date, disabled), selectedDates),
    prop('disabledDays', room)
  ),
  rooms
)

I am using the isSameDay function from date-fns as a predicate to test whether the dates are the same.


Solution

  • Using Ramda, I would use R.reject, and create a predicate with R.propSatisfies that uses R.any to match it agains the selectedDates with curried dateFns.isSameDay, and a flipped R.any:

    const { curry, reject, propSatisfies, any, pipe, flip } = R
    
    const eqByDate = curry(dateFns.isSameDay)
    
    const fn = selectedDates => reject(propSatisfies(
      any(pipe(
        eqByDate,
        flip(any)(selectedDates),
      )),
      'disabledDays',
    ))
    
    const rooms = [{ disabledDays: [], title: 'roomOne' }, { disabledDays: ['2019-07-10T01:00:00.000Z'], title: 'roomTwo' }, { disabledDays: [ '2019-07-08T01:00:00.000Z', '2019-07-09T01:00:00.000Z', '2019-07-02T01:00:00.000Z' ], title: 'roomThree' }, { disabledDays: [], title: 'roomFour' } ];
    const selectedDates = [ '2019-07-06T01:00:00.000Z', '2019-07-07T01:00:00.000Z', '2019-07-08T01:00:00.000Z', '2019-07-09T01:00:00.000Z' ];
    
    const result = fn(selectedDates)(rooms)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>