[英]Detect gaps in a sequence using Ramda?
In ramda.js, how can I detect if there is a gap in a sequence bigger than some value n? 在ramda.js中,如何检测序列中是否存在大于某个值n的间隙?
eg for values that have already been sorted: 例如,对于已经排序的值:
[
{"name":"bob", loginDate:"2017-10-01"},
{"name":"bob", loginDate:"2017-10-02"},
{"name":"bob", loginDate:"2017-10-03"},
{"name":"bob", loginDate:"2017-10-10"},
]
How would I detect if there has been a gap greater than 7 between the loginDates of any two records? 我如何检测两个记录的loginDate之间是否存在大于7的间隔? But not between the current and the first records - only checking against the previous one. 但不在当前记录与第一条记录之间-仅对照上一条进行检查。 I'm not sure how to compare the current item to the previous item in ramda. 我不确定如何将当前项目与ramda中的上一个项目进行比较。
When wanting to process adjacent values in a list it is often useful to create a list that can be traversed like a sliding window of values using R.aperture
. 当想要处理列表中的相邻值时,使用R.aperture
创建一个像值的滑动窗口一样可以遍历的列表通常很有用。
A binary function that performs the comparison between the previous and current items of a list can be wrapped in R.apply
so that it will accept an array of two elements to compare. 可以在R.apply
包装一个执行列表的前一项和当前项之间比较的二进制函数,这样它将接受两个要比较的元素的数组。
To illustrate with your example: 为了说明您的示例:
const maxGap = 1000 * 60 * 60 * 24 * 7 // 7 days in ms
const gtMaxGap = (prev, curr) =>
maxGap + Date.parse(prev.loginDate) < Date.parse(curr.loginDate)
const anyGapTooLarge = R.pipe(R.aperture(2), R.any(R.apply(gtMaxGap)))
anyGapTooLarge([
{"name":"bob", loginDate:"2017-10-01"},
{"name":"bob", loginDate:"2017-10-02"},
{"name":"bob", loginDate:"2017-10-03"},
{"name":"bob", loginDate:"2017-10-10"},
]) // false
Another alternative to R.aperture
would be to produce the list of adjacent values by using R.zip
to zip the list with its own tail. R.aperture
另一种选择是通过使用R.zip
用自己的尾部压缩列表来生成相邻值的列表。
As a student of functional programming, I worked on this problem. 作为函数编程的学生,我致力于解决这个问题。
I really like the answer by @Scott Christopher; 我真的很喜欢@Scott Christopher的回答; yet I manage work out a different solution before looking at what he did. 但在查看他的工作之前,我设法制定出另一种解决方案。
That approach follows: 该方法如下:
I worked through this a different way. 我以不同的方式工作。 If you want to have the a list of all logins after a given time period and note the difference in time, you could use essentially use reduce
then filter
for the gap 如果要在给定时间段后获得所有登录的列表,并记下时间差,则可以使用本质上使用reduce
然后filter
出差距
First, assume the data is contained sorted in a variable called data
首先,假设数据包含在名为data
的变量中
example 例
const logs = [
{"name":"bob", loginDate:"2017-10-01"},
{"name":"bob", loginDate:"2017-10-02"},
{"name":"bob", loginDate:"2017-10-03"},
{"name":"bob", loginDate:"2017-10-10"},
]
Next, we create a few utility functions and an iterator function 接下来,我们创建一些实用程序函数和一个迭代器函数
const dateDifference = nextDate => initDate => {
return ( new Date( nextDate ) - new Date( initDate ) )
}
const daysToMs = R.multiply(1000 * 60 * 60 * 24)
const differenceWithPreviousRecordIterator = dateField => differenceField => (acc,val) => {
const timeDifference = acc.length
? dateDifference
(val[dateField])
(R.last(acc)[dateField])
: 0
return R.append(
R.assoc( differenceField, timeDifference, val ),
acc
)
}
Now configure the iterator function 现在配置迭代器功能
const iteratorFunc = differenceWithPreviousRecordIterator('loginDate')('difference')
Then get the rows and filter for rows where logins occurred after the desired time 然后获取行并过滤所需时间后发生登录的行
const rowsWithDifference = R.reduce(iteratorFunc,[])(logs)
const sevenDaysAndOlder = R.where({
difference: R.gte( R.__, daysToMs(7) )
})
const filterForLoginsSevenDaysOrGreater = R.filter( sevenDaysAndOlder )
filterForLoginsSevenDaysOrGreater( rowsWithDifference )
// [ { name: 'bob', loginDate: '2017-10-10', difference: 604800000 } ]
That said, after looking @Scott's approach, a similar effect can be achieved by slightly modifying his solution. 也就是说,在查看@Scott的方法之后,可以通过稍微修改他的解决方案来达到类似的效果。 The modifications being namely that we're looking for a time equal to or greater than the gap instead of just greater than. 修改是,我们正在寻找等于或大于间隔而不是大于的时间。 The other is to simply use filter
instead of any
另一种是简单地使用filter
而不是any
const maxGap = 1000 * 60 * 60 * 24 * 7 // 7 days in ms
const gtMaxGap = (prev, curr) =>
maxGap + Date.parse(prev.loginDate) <= Date.parse(curr.loginDate)
const anyGapTooLarge = R.pipe(R.aperture(2), R.filter( R.apply( gtMaxGap ) ))
anyGapTooLarge([
{"name":"bob", loginDate:"2017-10-01"},
{"name":"bob", loginDate:"2017-10-02"},
{"name":"bob", loginDate:"2017-10-03"},
{"name":"bob", loginDate:"2017-10-10"},
]) // gives pair where login was greater than or equal to maxGap
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.