gpt4 book ai didi

kotlin - 如何在 Kotlin 中分块

转载 作者:行者123 更新时间:2023-12-02 18:05:11 25 4
gpt4 key购买 nike

在 Kotlin 中有分块的好方法吗?我需要一个包含总和小于 X 的连续元素 block 的列表。

示例 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 15 13 17 10] -> [[1, 2, 3, 4, 5], [6, 7], [8], [9], [10]](每个chunk的和小于16)

我认为分块方法可能会起作用,但我只能按大小分块。现在,我只是以命令式的方式制作了 for 循环。

最佳答案

更新

在尝试从 OP 获得一些关于规范的说明后,我只是将预期的输出与下面 @gidds 的回答对齐。

fun Iterable<Int>.chunkedBy(max: Int) = this.filter { it < max }
.fold(mutableListOf(mutableListOf<Int>())) { accumulator, current ->
accumulator.apply {
if (last().sum() + current > max - 1) add(mutableListOf(current))
else last().add(current)
}
}

class ExtensionTest : BehaviorSpec({

given("some input") {
val input = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 13, 17, 10)

val expected = listOf(
listOf(1, 2, 3, 4, 5),
listOf(6, 7),
listOf(8),
listOf(9),
listOf(10),
listOf(14),
listOf(15),
listOf(13),
listOf(10)
)

`when`("folding") {

val result = input.chunkedBy(16)

then("result should be as expected") {
result shouldBe expected
}
}
}
})

原始答案

经过测试,这个问题主要有两个方面。

  • 创建一个仅包含连续数字的新集合
  • 将连续的数字映射到列表的列表中

对于前一部分,while循环是合适的,因为不再满足条件时很容易退出。这不是直截了当的,例如filter .

对于后半部分,fold可用于将连续数字列表映射(减少)为列表列表。

请注意,除了 val result ,只使用一个显式声明:var index .

代码是在 Kotest 中编写的。

import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe

class MyTest : BehaviorSpec({

given("some input") {
val input = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 13, 17, 10)

val expected = listOf(
listOf(1, 2, 3, 4, 5),
listOf(6, 7),
listOf(8),
listOf(9),
listOf(10)
)

`when`("folding") {

val result = mutableListOf(input[0]).apply {
/** build a list of consecutive numbers only */
var index = 1
while (index < input.size
&& input[index] < 16
&& last() == input[index] - 1
) add(input[index++])
}.fold(mutableListOf(mutableListOf<Int>())) { accumulator, current ->
accumulator.apply {
/** if sum of current "chunk" will be greater than 15 */
if (last().sum() + current > 15) add(mutableListOf(current))
/** add element to current "chunk" */
else last().add(current)
}
}

then("result should be as expected") {
result shouldBe expected
}
}
}
})

可能会精简到 8 行,仍然可以通过 checkstyle(只是为了与其他可读性不同的答案进行比较)

val result = mutableListOf(input[0]).apply {
var index = 1
while (index < input.size && input[index] < 16 && last() == input[index] - 1) add(input[index++])
}.fold(mutableListOf(mutableListOf<Int>())) { accumulator, current ->
accumulator.apply {
if (last().sum() + current > 15) add(mutableListOf(current)) else last().add(current)
}
}

apply : 使用 this 的扩展方法在内部返回接收者,而不是 run返回 lambda 的结果。

alsoletapply的对应物和 run正在使用 it内部。

也测试过

代码应该处理输入中出现新的连续数字序列的情况,例如:

val input = listOf(1, 2, 3, 4, 5, 8, 6, 7)
val expected = listOf(listOf(1, 2, 3, 4, 5))

关于kotlin - 如何在 Kotlin 中分块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73424592/

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