使用带有 ramda 的谓词相互过滤两个列表

Filter two lists against each other using predicate with ramda

我有一组房间,每个房间都包含另一组 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 在其 disabledDays 数组中具有 noneselectedDates

到目前为止,我的尝试使用了 maprejectany 的组合,但这似乎并没有 return 整个房间。

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

我正在使用 date-fns 中的 isSameDay 函数作为谓词来测试日期是否相同。

这是一种方法的 ES6lodashRamda 版本。我用 filterany/some 走了一条不同的路线,因为这对我来说更有意义。我相信你也可以用 reject 来做,但我不确定你会从 map 开始,因为 map 会期望 return 相同的 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 aficionados。希望这会有所帮助。

使用 Ramda,我会使用 R.reject,并创建一个带有 R.propSatisfies 的谓词,使用 R.any 再次匹配 selectedDates 和 curried 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>

我忽略了你对 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>