Groovy -从数组中过滤出间隔小于x天的日期

vxbzzdmp  于 2023-03-01  发布在  其他
关注(0)|答案(2)|浏览(194)

我有一个日期数组

[2020-06-17,
2020-06-21,
2020-06-22,
2020-06-26,
2020-08-03,
2020-08-05,
2020-08-13,
2020-09-16,
2020-11-18,
2021-01-10,
2021-01-15]

我想得到一个新的数组,其中只包含那些在至少一个其他日期的7天内的日期。

[2020-06-17,
2020-06-21,
2020-06-22,
2020-06-26,
2020-08-03,
2020-08-05,
2021-01-10,
2021-01-15]

如您在示例中所见,2020-06-26与2020-06-17的间隔超过7天,但与2020-06-21和2020-06-22的间隔小于7天。
任何关于如何做到这一点的想法都将不胜感激。
谢谢!

fwzugrvs

fwzugrvs1#

一个简单而低效的解决方案是遍历列表,过滤掉列表中所有在7天内有其他日期的元素。给定名为dates的数组LocalDate[],并假设数组中没有重复项(或者重复项不应被考虑):

LocalDate[] result = dates.findAll { d1 ->
    dates.find { d2 -> d1 != d2 && (d1 - d2).abs() <= 7 }
}

请注意,groovy-datetime库需要以这种方式减去天数(d1 - d2)。这是由groovy-all自动提供的,而不是由groovy提供的。

解释

Object[]上的findAll方法用于返回与给定结束条件匹配的日期。

dates.findAll { d1 -> ... }

闭包在Collection上使用find方法返回与给定条件匹配的第一个元素,如果不匹配则返回null

dates.find { d2 -> ... }

由于null是假的,而所有LocalDate值都是真的,因此外部findAll调用只包括内部find返回值的值。
最后,find使用的闭包检查这两个日期是否不同(从而跳过检查相同索引的情况,以及跳过任何重复的日期),它还确认这两个日期之间的天数是7天或更少。

{ d2 -> d1 != d2 && (d1 - d2).abs() <= 7 }

根据Groovy添加到该类中的minus方法,将两个LocalDate值相减会返回这两个日期之间的天数。对于每个Number.abs,取差值的绝对值会将结果规范化为正数,而不管较小日期或较大日期是在前面。

83qze16e

83qze16e2#

正如this answer中提到的,二次时间的解决方案非常简单,下面的解决方案具有更好的时间复杂度- O(n log n)-代价是不太简单的解决方案和复制/排序输入数据。

List<LocalDate> sortedDates = dates.sort(false)
LocalDate[] result = sortedDates.withIndex().findResults { d ->
    def (LocalDate date, int index) = d
    LocalDate previous = index == 0 ? null : sortedDates[index - 1]
    LocalDate next = index == sortedDates.size() - 1
            ? null : sortedDates[index + 1]

    return (previous && date - previous <= 7)
            || (next && next - date <= 7) ? date : null
}

这个解决方案的工作原理是对数据进行排序,并检查每条记录的邻居是否在它的7天之内,如果是,它就包含在结果数组中,如果不是,它就被排除。

相关问题