【问题标题】:Functional way to write while loop with mutable variable使用可变变量编写 while 循环的函数式方法
【发布时间】:2017-06-12 16:53:15
【问题描述】:

我需要获取一个集合,该集合应在某些输入和LocalDatetime.now 之间填充日期时间间隔。

例子:

如果我要建立一个基于每 30 分钟的间隔,它应该类似于 2017-06-12 00:30, 2017-06-12 01:00, 2017-06-12 01:30, 2017-06-12 02:00..and go on

我已经编写了一个符合我要求的代码,但它看起来像使用 Scala 语法的 Java - 不是一种功能性和更简洁的方式。

  val now = LocalDateTime.now
  val dates = if (interval.toInt > 0) {
    var tempDate = LocalDate.now.atStartOfDay()
    val allDates = scala.collection.mutable.ListBuffer[String]()
    while (tempDate.isBefore(now)) {
      allDates += tempDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
      tempDate = tempDate.plusMinutes(interval.toInt)
    }
    allDates
  } else {
    var initialDay = LocalDate.now.minusDays(30)
    val allDates = scala.collection.mutable.ListBuffer[String]()
    while (initialDay.isBefore(LocalDate.now)) {
      allDates += initialDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
      initialDay = initialDay.plusDays(1)
    }
    allDates
  }

如何重构此代码以使其看起来像函数式样式或至少删除该可变变量?

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    您应该使用 Scala 的 Stream 类型以半小时为增量从开始日期构建一个惰性流,然后从早于停止日期的日期中惰性地获取尽可能多的日期。例如:

    def halfHoursFrom(start: LocalDateTime): Seq[LocalDateTime] =
      Stream
        .iterate(start)(_.plusMinutes(30))
        .takeWhile(_.isBefore(LocalDateTime.now))
    

    您将在标准库参考中找到Stream 类型的文档。我们在这里使用的两个值得注意的方法是:

    • Stream.iterate(在 Stream 伴生对象中):从起始值和增量函数懒惰地构建无限流
    • Stream#takeWhile(在Stream 类中):只从给定流中获取与给定谓词匹配的元素(测试每个元素并返回true/false 的函数)。

    请注意,我将返回类型向上转换为 Seq[LocalDateTime] 以向调用者隐藏实现细节。

    【讨论】:

    • 这是一个很好的答案。我将添加一个在我开始使用 Scala 时让我感到困惑的提示:Stream 是惰性求值的,但它确实缓存了它计算的所有元素,因此它会占用内存。因此,在替换 while 循环 + 可变 var 时,这种模式并不总是适用,因为如果不在每次迭代中收集结果,它可能会导致更糟糕的内存使用。如果您不想保存每次迭代的中间结果,Iterator.iterate 是一个不以这种方式使用内存的等价物。
    • @JoeK 好点,仔细记下确切的要求是很好的。在这种情况下,请求是要求将日期集合作为返回值,但经过一番思考,请求者可能会发现他们可以在日期序列上使用迭代器。
    猜你喜欢
    • 2017-06-18
    • 2019-09-06
    • 1970-01-01
    • 2022-07-07
    • 2013-03-26
    • 2016-08-05
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多