gpt4 book ai didi

list - Kotlin:以功能性方式组合列表中的某些元素

转载 作者:行者123 更新时间:2023-12-04 17:14:31 25 4
gpt4 key购买 nike

最近,有人问我可以建议我使用Kotlin stdlib的哪些功能来处理某个问题:将具有相同开始/结束时间的某些 session 合并到一个列表中。

假设这个数据类召开了一次 session :

data class Meeting(val startTime: Int, val endTime: Int)

fun main() {
val meetings = listOf(
Meeting(10, 11),
Meeting(12, 15), // this can be merged with
Meeting(15, 17) // this one
)
println(combine(meetings))
// should print: [Meeting(startTime=10, endTime=11), Meeting(startTime=12, endTime=17)]
}

fun combine(meetings: List<Meeting>): List<Meeting> {
// TODO: elegant, functional way to do this?
}

我已经使用 fold解决了这个问题,但是我不认为这是正确的用法(一个简单的forEach应该就足够了):
fun combine(meetings : List<Meeting>) : List<Meeting> {
return meetings.fold(mutableListOf<Meeting>()) { combined: MutableList<Meeting>, meeting: Meeting ->
val lastMeeting = combined.lastOrNull()
when {
lastMeeting == null -> combined.add(meeting)
lastMeeting.endTime == meeting.startTime -> {
combined.remove(lastMeeting)
combined.add(Meeting(lastMeeting.startTime, meeting.endTime))
}
else -> combined.add(meeting)
}
combined
}.toList()
}

另外,用 forEach代替 fold的另一种解决方案:
fun combine(meetings: List<Meeting>): List<Meeting> {
val combined = mutableListOf<Meeting>()

meetings.forEachIndexed { index, meeting ->
val lastMeeting = combined.lastOrNull()
when {
lastMeeting == null -> combined.add(meeting)
lastMeeting.endTime == meeting.startTime ->
combined[combined.lastIndex] = Meeting(lastMeeting.startTime, meeting.endTime)
else -> combined.add(meeting)
}
}

return combined.toList()
}

但是,我觉得必须有一种更优雅,更实用且可变性更少的方法来解决此问题。您将如何处理?

哦,在我忘记之前:当然,我有一些单元测试供您使用! 😇
@Test
fun `empty meeting list returns empty list`() {
val meetings = emptyList<Meeting>()
assertEquals(emptyList<Meeting>(), combine(meetings))
}

@Test
fun `single meeting list returns the same`() {
val meetings = listOf(Meeting(9, 10))
assertEquals(meetings, combine(meetings))
}

@Test
fun `3 different meetings`() {
val meetings = listOf(Meeting(9, 10), Meeting(11, 12), Meeting(13, 14))
assertEquals(meetings, combine(meetings))
}

@Test
fun `2 meetings that can be merged`() {
val meetings = listOf(Meeting(9, 10), Meeting(10, 11))
assertEquals(listOf(Meeting(9, 11)), combine(meetings))
}

@Test
fun `3 meetings that can be merged`() {
val meetings = listOf(Meeting(9, 10), Meeting(10, 11), Meeting(11, 13))
assertEquals(listOf(Meeting(9, 13)), combine(meetings))
}

这是一个 Kotlin Playground link入门。

非常感谢你的帮助! 😊

最佳答案

这是一种实用的方法。想法是将所有 session 端点都放在一个列表中,然后比较相邻的endTime和startTime对,并过滤掉相等的对。
然后将结果分成几对,并从中得出 session 的结果列表。

fun combine(meetings: List<Meeting>): List<Meeting> {
return meetings
.zipWithNext { current, next -> listOf(current.endTime, next.startTime) }
.filterNot { (end, start) -> end == start }
.flatten()
.let { listOf(meetings.first().startTime) + it + listOf(meetings.last().endTime) }
.chunked(2) { (start, end) -> Meeting(start, end) }
}

它适用于非空 session 列表;处理空的是在开始时进行额外的 if (meetings.isEmpty()) return meetings检查的问题。

但是,我觉得它并不优雅,因为它需要大量的对象分配来容纳大量的 session 。在操作链的开始使用 meetings函数将 .asSequence()转换为序列可能会有所帮助,但并没有太大帮助。

关于list - Kotlin:以功能性方式组合列表中的某些元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57665638/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com