Kotlin 在多个索引处将 Arraylist 拆分为多个部分

Posted

技术标签:

【中文标题】Kotlin 在多个索引处将 Arraylist 拆分为多个部分【英文标题】:Kotlin splitting an Arraylist into parts at more than one Index 【发布时间】:2019-04-28 17:14:40 【问题描述】:

假设我有一个 Arraylist

fun main() 
var myarrayList= ArrayList<String>()

myarrayList.add("+23")
myarrayList.add("-25")
myarrayList.add("+125")
myarrayList.add("+455")
myarrayList.add("")
myarrayList.add("*230")
myarrayList.add("-293")
myarrayList.add("/6")
myarrayList.add("")
myarrayList.add("+293")
myarrayList.add("")
myarrayList.add("+21")

for (index in 0..myarrayList.size-1)
    print (index)
    print (" = ")
    print (myarrayList.get(index))
    print ("\n")


 

我想在 value = "" 的每个索引处将其拆分为较小的 Arraylist。我知道我可以使用 indexOf() 和 lastIndexOf 对其进行切片,但我只能获得 2 个切片。我需要拆分成多个数组

【问题讨论】:

【参考方案1】:

你绝对可以在这里使用arrayList的.sublist函数:

fun subList(fromIndex: Int, toIndex: Int): MutableList<E>

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-array-list/sub-list.html

【讨论】:

我实际上已经用一个粗略的子列表版本来管理它,但它非常混乱。我认为可能有更清洁的方法。顺便说一句,您的回复,【参考方案2】:

我无法想象没有更简单的方法可以做到这一点......实际上有很多方法可以解决它,但都有一个或另一个“缺陷”(例如,你需要添加一些前面或末尾的索引...或者您需要注意不要丢失最后一个条目,因为没有最终的"" 等)。如果您一开始就不需要列表列表,那么它可以很简单:

myarrayList.joinToString("") 
  if (it == "") "\n" else it

它基本上只返回一个String,如下所示:

+23-25+125+455
*230-293/6
+293
+21

也许这给了你一个提示,joinToString 可能已经有什么其他可能...现在仍在使用 joinToString 但只是相应地拆分它(显然是一种解决方法):

myarrayList.joinToString("|") 
  if (it == "") "FORM_END" else it
.splitToSequence("|FORM_END|") // use split if List<*> is ok for you
    .map 
      it.splitToSequence("|")   // use split if *<List<String>> is ok for you
    

这现在基本上会给你一个序列序列。添加.map it.toList() .forEach(::println) 将得到以下结果:

[+23, -25, +125, +455]
[*230, -293, /6]
[+293]
[+21]

另一种方法,不使用joinToString-workaround,而是使用mapIndexedNotNullzipWithNext,其打印结果与以前相同:

myarrayList.mapIndexedNotNull  i, s -> i.takeIf  s == ""  
    .let 
      listOf(-1) + it + myarrayList.size // ugly, but we need beginning and end too, not only the delimiting indices
    
    .asSequence()
    .zipWithNext  from, upto -> myarrayList.subList(from + 1, upto) 
    .forEach(::println)

您也可以使用fold 构建一些东西...但请务必同时收集列表的最后一个条目;-)

【讨论】:

感谢 Roland 非常明确的回答。我曾考虑过使用 JoinToString,我认为这可能是最干净的方法。在上面的示例中,我实际上并没有只使用单个数字。它是一种带有运行列表的计算器应用程序,就像带有纸卷的旧式桌面一样。 Arraylist 中的每一行将代表计算中的一行。一世。 e 一个数据类rowItem(lineNos, value, note) 好吧...可能是最易读的,但如果您首先不需要连接字符串,也是一种解决方法;-)【参考方案3】:

我一直在寻找同样的东西,最终我为List 创建了自己的扩展函数。

fun <E> List<E>.split(separator: E): List<List<E>> =
    mutableListOf<List<E>>().also  result ->
        var end = -1
        var remaining = this

        while (end < remaining.size) 
            remaining = remaining.drop(end + 1)
            end = remaining.indexOf(separator).let 
                if (it == -1) remaining.size else it
            
            result.add(remaining.subList(0, end))
        
    

【讨论】:

这应该是一个可以接受的答案。我添加了一个可以为空的分隔符:fun List.split(separator: E?): List>。现在,您可以使用它来分隔空元素的列表。例如: val list = listOf(1, 2, null, 4, 5, 6) list.split(null) print : [ [1, 2], [4, 5, 6] ]【参考方案4】:

您可以使用集合函数的组合来解决您的问题。 首先你应该找到空字符串的索引(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-indexed-not-null.html):

val splitPoints =
    myarrayList.mapIndexedNotNull()  idx, str -> if (str.isEmpty()) idx else null 

接下来您可以使用windowed 从列表中连续获取两个项目。要获取列表的第一部分和最后一部分,您需要添加 -1 和 ArrayList 的大小。现在您可以使用sublist 并提取各个部分:

val splittedList =
    (listOf(-1)  + splitPoints + myarrayList.size)
        .windowed(2, 1)
        .map  (start, end) -> myarrayList.subList(start + 1, end) 

【讨论】:

【参考方案5】:

我对 Kotlin /Anko 很陌生,并意识到您的答案涉及 RXKotlin。我从来没有听说过windowed,但查了一下。它要学习的更多。但是,我已经能够使用以下代码实现相同的目的。非常感谢大家的帮助

有趣的 main()

var myarrayList= ArrayList<String>()
var emptyIndexes= ArrayList<Int>()
emptyIndexes.add(0)



myarrayList.add("+23")
myarrayList.add("-25")
myarrayList.add("+125")
myarrayList.add("+455")
myarrayList.add("")
myarrayList.add("*230")
myarrayList.add("-293")
myarrayList.add("")
myarrayList.add("+293")
myarrayList.add("")
myarrayList.add("+21")

for (index in 0..myarrayList.size-1)
    print (index)
    print (" = ")
    print (myarrayList.get(index))
    print ("\n")

    ///find empty index
    if (myarrayList.get(index)=="")
       emptyIndexes.add(index)

     



 emptyIndexes.add(myarrayList.size)

 print("\n")

    for (item in emptyIndexes)

    print ("empty index "+ item +" ")





for (index in 0..emptyIndexes.size-1)

        //println ("start index " +index) 
        if (index==emptyIndexes.size-1)break
        //println ("end index "+ (index+1) )

       // print("\n\nemptyIndixes size)"+ emptyIndexes.size +"\n\n")

        var subCals=myarrayList.subList(emptyIndexes[index],emptyIndexes[(index+1)])
        //println (subCals )
        var stToCal=""
        for (items in subCals)

            stToCal=stToCal+items.toString()



        


     

【讨论】:

以上是关于Kotlin 在多个索引处将 Arraylist 拆分为多个部分的主要内容,如果未能解决你的问题,请参考以下文章

Jquery在某个索引处将新行插入表中

在预定义索引处将数据行添加到数据表

如何在一个已经在python中保存整数值的索引处将字符分配给字符串?

在给定的标签处将 XML 文件拆分为多个

在每个谓词 scala 处将字符串列表拆分为多个列表

Kotlin singleton:如何从singleton复制对象