Kotlin-收集基于创建日期的特定日期范围之间存在的所有项目?

q8l4jmvw  于 2023-04-21  发布在  Kotlin
关注(0)|答案(2)|浏览(134)

我正在根据特定的输入开始和结束时间(如Instant)收集项目。
这些项目如下所示:

data class Item (val created: Instant, val name: String)

当我试图做的是得到所有的项目之间存在一个特定的开始和结束时间。所以作为一个例子(只是为了简单起见,假设秒在这里):

Item1 - created: 2 seconds
Item2 - created: 5 seconds
Item3 - created: 9 seconds
Item4 - created: 12 seconds

给定输入getItem(from = 3 seconds, to = 13 seconds),我应该得到返回的所有项,因为尽管Item1不是在3秒后创建的,但它在Item2创建之前就存在了。
或者,如果输入是getItem(from = 5 seconds, to = 9 seconds),我应该只得到项目2和3,因为它们是在整个范围内创建和存在的。
在Kotlin中做这件事的最好方法是什么?
获取在输入范围之间创建的项相当简单,看起来像这样(假设项已排序):

items.filter {
    it.created.isAfter(start) && it.created.isBefore(end)
}

但这会遗漏输入中可能已经存在但不是在输入期间创建的项。

jtw3ybtb

jtw3ybtb1#

你只需要跟踪上一个值。类似这样的东西应该可以工作:

fun Iterable<Item>.getActiveItems(start: Instant, end: Instant): List<Item> {
    require(end >= start)
    var prev: Item? = null
    val result = mutableListOf<Item>()
    for (item in this) {
        if (item.created <= start) prev = item else {
            prev?.let(result::add)
            prev = null
            result += item.takeIf { it.created <= end } ?: break
        }
    }
    return result
}

假设:

  • 列表按created排序
  • 包含start处的created项,但不包含之前的任何项
  • 包含end处的项目created,但不包含之后的任何项目
tkclm6bt

tkclm6bt2#

这是一个基于索引迭代的解决方案,但与@Ruckus T-Boom的答案的一般原理相同。

fun List<Item>.getItems(from: Instant, to: Instant): List<Item> {
    var startIndex: Int? = null
    var endIndex: Int? = null
    run loop@ {
        this.forEachIndexed { i, item ->
            if (startIndex == null) {
                when {
                    item.created > from -> startIndex = i - 1
                    item.created == from -> startIndex = i
                }   
            }
            if (endIndex == null) {
                when {
                    item.created > to -> endIndex = i - 1
                    item.created == to -> endIndex = i
                }
            }
            if (startIndex != null && endIndex != null) {
                return@loop
            }
        }
    }
    if (startIndex == null) {
        return emptyList()
    }
    if (endIndex == null) {
        endIndex = this.size - 1
    }
    return this.subList(startIndex!!, endIndex!! + 1)
}

这并没有涵盖所有可能的边缘情况,但是很好地处理了您的示例中的情况以及其他一些情况(您可以自己检查here

相关问题