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

时间:2019-06-23 00:56:37

标签: javascript arrays filter ramda.js

我有一个房间阵列,每个房间包含另一个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数组中没有selectedDates的{​​{1}}的{​​{1}}。

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

any

我使用const result = map( room => reject( date => any(disabled => isSameDay(date, disabled), selectedDates), prop('disabledDays', room) ), rooms ) 中的isSameDay函数作为谓词来测试日期是否相同。

3 个答案:

答案 0 :(得分:3)

使用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>

答案 1 :(得分:2)

以下是一种方法的ES6lodashRamda版本。我使用filterany/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 aficionados 。希望这会有所帮助。

答案 2 :(得分:2)

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