如何使用Kotlin的谓词将列表拆分为子列表? [英] How to split a list into sublists using a predicate with Kotlin?

查看:56
本文介绍了如何使用Kotlin的谓词将列表拆分为子列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试一种惯用且理想的功能方式,将列表分成Kotlin中的子列表.

I am trying an idiomatic, and ideally functional way to split a list into sublists in Kotlin .

假设输入是 ["aaa","bbb",","ccc",","ddd","eee","fff",] ,我想返回 [["aaa","bbb"],["ccc"],["ddd","eee","fff"]]给定谓词 string.isEmpty().

Imagine the input being ["aaa", "bbb", "", "ccc", "", "ddd", "eee", "fff"], I want to return [["aaa", "bbb"], ["ccc"], ["ddd", "eee", "fff"]] for the given predicate string.isEmpty().

使用for循环和累加器非常简单;但我还没有找到一种方法来编写我认为足够可读的功能.

It is quite simple to do with a for loop and an accumulator; but I haven't found a way to write it functionally that I find readable enough.

到目前为止,我最好的结果是:

So far my best outcome is :

lines.foldIndexed(Pair(listOf<List<String>>(), listOf<String>()), { idx, acc, line ->
    when {
    idx + 1 == lines.size -> {
        Pair(acc.first + listOf(acc.second + line), listOf())
    }
    line.isEmpty() -> {
        Pair(acc.first + listOf(acc.second), listOf())
    }
    else -> {
        Pair(acc.first, acc.second + line)
        }
    }
}).first

本质上,我正在使用 fold 和双累加器,该累加器跟踪当前列表并在找到谓词时重置.此时,列表将输入完整的结果.我正在使用 foldIndexed 得到我的最后一个清单.

Essentially, I am using a fold with a double accumulator that keeps track of the current list and resets when the predicate is found. The list feeds into the complete result at that point. I am using a foldIndexed in order to get my last list in.

您知道其他更好的方法吗?

Do you folks know of any better way ?

作为参考,可以使用循环版本

For reference, a loop version could be

val data = mutableListOf<String>()
var currentData = ""
for(line in lines){
    if(line.isEmpty()) {
        data.add(currentData)
        currentData = ""
    }
    else{
        currentData = "$currentData $line"
    }
}
data.add(currentData)

谢谢!

推荐答案

我建议先找到分割点(手动添加边缘索引),然后再进行切片:

I'd suggest to find splitting points (manually adding edge indices) first and then do slices:

val lines = listOf("aaa", "bbb", "", "ccc", "", "ddd", "eee", "fff")
val result = lines
    .flatMapIndexed { index, x ->
        when {
            index == 0 || index == lines.lastIndex -> listOf(index)
            x.isEmpty() -> listOf(index - 1, index + 1)
            else -> emptyList()
        }
    }
    .windowed(size = 2, step = 2) { (from, to) -> lines.slice(from..to) }
println(result) //[[aaa, bbb], [ccc], [ddd, eee, fff]]

这篇关于如何使用Kotlin的谓词将列表拆分为子列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆