Фильтруйте два списка друг против друга, используя предикат с ramda - PullRequest
0 голосов
/ 23 июня 2019

У меня есть массив комнат, в каждой из которых есть еще один массив 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'
];

В этом случае я хочу найти rooms с none из selectedDates в их массиве disabledDays.

Моя попытка до сих пор использует комбинацию map, reject и any, однако в результате этого, похоже, не возвращается полная комната.

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

Я использую функцию isSameDay из date-fns в качестве предиката, чтобы проверить, совпадают ли даты.

Ответы [ 3 ]

3 голосов
/ 23 июня 2019

Используя Ramda, я бы использовал R.reject и создал бы предикат с R.propSatisfies, который использует R.any для сопоставления его с selectedDates с карри dateFns.isSameDay и перевернутым 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>
2 голосов
/ 23 июня 2019

Я упустил из виду вашу зависимость от date-fns.Однако, если с этими строками вам нужно работать, то простое сравнение строк должно сработать?Если вам нужно работать с date-fns, то, возможно, вам нужен ответ Ori Drori


Вы можете использовать intersection, чтобы найти общие даты между двумя списками дат.

Затем вы можете построить предикат, в котором будут храниться все комнаты, для которых нет общих дат:

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 z = (dates, rooms) =>
  filter(propSatisfies(compose(isEmpty, intersection(dates)), 'disabledDays'), rooms);

console.log(
  z(selectedDates, rooms)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {intersection, filter, propSatisfies, compose, isEmpty} = R;</script>
2 голосов
/ 23 июня 2019

Вот версии ES6, lodash и Ramda одного подхода.Я пошел другим путем с filter и any/some, так как это имело для меня больше смысла.Я уверен, что вы также можете сделать это с reject, но я не уверен, что вы начнете с map , так как map будет ожидать тот же массив length:

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' ];

let js = rooms.filter(({ disabledDays, title}) =>
  !disabledDays.some(d => selectedDates.some(s => dateFns.isSameDay(d,s))))

let lodash = _.filter(rooms, r => 
  !_.some(r.disabledDays, d => _.some(selectedDates, s => dateFns.isSameDay(d,s))))

let r = R.filter(r => !R.any(d => R.any(s => 
  dateFns.isSameDay(d,s), selectedDates), r.disabledDays), rooms)

console.log('js: ', js)
console.log('_: ', lodash)
console.log('R: ', r)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>

Я уверен, что версия Ramda могла бы быть более краткой, но я оставлю это для поклонников Ramda поклонников здесь.Надеюсь, это поможет.

...