使用带有 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
数组中具有 none 的 selectedDates
。
到目前为止,我的尝试使用了 map
、reject
和 any
的组合,但这似乎并没有 return 整个房间。
const result = map(
room => reject(
date => any(disabled => isSameDay(date, disabled), selectedDates),
prop('disabledDays', room)
),
rooms
)
我正在使用 date-fns
中的 isSameDay
函数作为谓词来测试日期是否相同。
这是一种方法的 ES6
、lodash
和 Ramda
版本。我用 filter
和 any/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>
我有一组房间,每个房间都包含另一组 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
数组中具有 none 的 selectedDates
。
到目前为止,我的尝试使用了 map
、reject
和 any
的组合,但这似乎并没有 return 整个房间。
const result = map(
room => reject(
date => any(disabled => isSameDay(date, disabled), selectedDates),
prop('disabledDays', room)
),
rooms
)
我正在使用 date-fns
中的 isSameDay
函数作为谓词来测试日期是否相同。
这是一种方法的 ES6
、lodash
和 Ramda
版本。我用 filter
和 any/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>