该循环的功能等效项

k31*_*159 3 kotlin

我正在尝试使用现代函数式语言功能重构以下函数,使其更加符合 Kotlin 习惯:

fun foobar(): List<Account> {
    var pageOffset = 0
    val accounts: MutableList<Account> = ArrayList()
    var chunk: List<Account> = accountsService.getAccounts(pageOffset, MAX_POLL_SIZE)
    while (chunk.isNotEmpty()) {
        accounts.addAll(chunk)
        pageOffset += MAX_POLL_SIZE
        chunk = accountsService.getAccounts(pageOffset, MAX_POLL_SIZE)
    }
    return accounts
}
Run Code Online (Sandbox Code Playgroud)

我的第一次尝试是用 buildList 替换可变列表,但它仍然不是很实用的风格:

fun foobar2(): List<Account> {
    var pageOffset = 0
    return buildList {
        var chunk: List<Account> = accountsService.getAccounts(pageOffset, MAX_POLL_SIZE)
        while (chunk.isNotEmpty()) {
            addAll(chunk)
            pageOffset += MAX_POLL_SIZE
            chunk = accountsService.getAccounts(pageOffset, MAX_POLL_SIZE)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想用while类似的东西替换整个循环accountsService.getAccounts(...).map { ... },但我不知道如何重构一个 while 循环,该循环具有这种“第一个块”,后跟许多其他块。能做到吗?

Swe*_*per 6

你可以这样做:

fun foobar(): List<Account> =
    generateSequence(0) { it + MAX_POLL_SIZE }.map { offset ->
        accountsService.getAccounts(offset, MAX_POLL_SIZE)
    }.takeWhile { it.isNotEmpty() }.flatten().toList()
Run Code Online (Sandbox Code Playgroud)

generateSequence0生成一个以、MAX_POLL_SIZEMAX_POLL_SIZE * 2MAX_POLL_SIZE * 3等开头的无限惰性序列。这是您要获取帐户的页面偏移量的序列。我们使用 ,将每个页面偏移量转换为它对应的帐户列表map。之后,我们使用 指定无限序列的结束takeWhile

现在我们有了 a Sequence<List<Account>>,所以我们使用将flatten其转换为 a Sequence<Account>,然后可以简单地将其转换为 a List<Account>

  • @lukas.j 没有?种子是第一个元素。`println(generateSequence(0) { it + 10 }.take(10).toList())` 打印 `[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]`。 (2认同)