Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据Kotlin中的条件将列表拆分为连续元素组_Kotlin - Fatal编程技术网

根据Kotlin中的条件将列表拆分为连续元素组

根据Kotlin中的条件将列表拆分为连续元素组,kotlin,Kotlin,我试图根据某种类型和顺序对列表进行分组 data class Item(val type: Int, val name: String) private fun splitItems(items: List<Item>): List<List<Item>> { val groupedItems = mutableListOf<List<Item>>() var tempList = mutableListOf<I

我试图根据某种类型和顺序对列表进行分组

data class Item(val type: Int, val name: String)

private fun splitItems(items: List<Item>): List<List<Item>> {
    val groupedItems = mutableListOf<List<Item>>()
    var tempList = mutableListOf<Item>()
    items.mapIndexed { index, item ->
        if (index > 0) {
            val previousItem = items[index - 1]
            if (previousItem.type == item.type) {
                tempList.add(item)
            } else {
                if (tempList.isNotEmpty()) groupedItems.add(tempList)
                tempList = mutableListOf()
                tempList.add(item)
            }
        } else tempList.add(item)
    }
    if (tempList.isNotEmpty()) groupedItems.add(tempList)
    return groupedItems
}
返回

[Item(type=1, name=Shirt), Item(type=1, name=Shirt)]
[Item(type=2, name=Pant), Item(type=2, name=Pant), Item(type=2, name=Pant)]
[Item(type=1, name=Shirt), Item(type=1, name=Shirt)]
[Item(type=3, name=Tee), Item(type=3, name=Tee)]
[Item(type=2, name=Pant), Item(type=2, name=Pant)]
[Item(type=1, name=Shirt), Item(type=1, name=Shirt), Item(type=1, name=Shirt)]
这是预期的工作。由于我正在尝试学习Kotlin,而且我知道有一种很好的方法可以做到这一点,我想知道如何用Kotlin的方法简化这个逻辑。

这是原始解决方案的原始答案。要获得更好的(imo)实施,请滚动至编辑

一些语言,如Kotlin,采用一元函数
(T)->U
并返回一个字典,将每个
U
映射到映射到它的
T
列表,从而实现
groupBy
。其他语言,如Haskell,使用
(T,T)->布尔
谓词,对满足谓词的连续元素进行分组

Kotlin中没有任何功能可以方便地支持您希望使用的操作。因此,您必须实现自己的。比您的代码略短的代码是:

fun <T> Iterable<T>.groupConsecutiveBy(predicate: (T, T) -> Boolean): List<List<T>> {
    var leftToGroup = this.toList()
    val groups = mutableListOf<List<T>>()

    while (leftToGroup.isNotEmpty()) {
        val firstItem = leftToGroup[0]
        val newGroup = leftToGroup.takeWhile { predicate(it, firstItem) }
        groups.add(newGroup)
        leftToGroup = leftToGroup.subList(newGroup.size, leftToGroup.size)
    }

    return groups
}
这将产生:

在这里,我们对任何
T
Iterable
使用na扩展方法。这是在Kotlin中引入此类功能的惯用方法,因为这是一个由任何
Iterable
完成的操作。我还使它成为通用(
T
)并接受任何将用连续元素测试的
谓词


编辑:实际上,有一个功能可以将每个元素逐个累加到某个结构中。它有时被称为累积、减少,或者在Kotlin中称为折叠:

fun Iterable.groupconsutiveby(groupIdentifier:(T,T)->布尔值)=
如果(!this.any())
空列表()
除此之外
.下降(1)
.fold(mutableListOf(mutableListOf(this.first())){groups,t->
groups.last().apply{
if(groupIdentifier.invoke(last(),t)){
加(t)
}否则{
groups.add(mutableListOf(t))
}
}
组
}
这是一个单一的表达方式,可以说比前一个表达方式更加地道。它不使用原始循环,也不在代码部分之间保持状态。它也很简单,或者所讨论的
Iterable
是空的,在这种情况下,我们返回一个空列表,或者,如果存在元素,我们将它们折叠成一个组列表(
list
of
list
s)


请注意
下拉列表(1)
-之所以这样做,是因为我们
将所有元素折叠到已包含该元素的最终列表中(通过
折叠()调用中的构造)。通过这样做,我们可以避免引入额外的列表空检查。

您应该使用分区

val array = intArrayOf(1, 2, 3, 4, 5)
val (even, odd) = array.partition { it % 2 == 0 }
println(even) // [2, 4]
println(odd) // [1, 3, 5]

使用类型为键、ArrayList为值的HashMap。请问您的使用案例是什么?通常我们会使用
groupBy
或类似的实用程序,但它不会在结果中保留“序列”信息。所以我想知道为什么您需要这个数据结构作为输出。实际上,项目是根据时间排序的,我需要保留序列。另一种方法可能会使用。  (对不起,现在没有时间写东西,前面的问题中可能有一些例子。  或者它会成为一个有指导意义的练习:-)这只是为了一分为二。
fun main() {
    val items = mutableListOf(
        Item(1, "Shirt"),
        Item(1, "Shirt"),
        Item(2, "Pant"),
        Item(2, "Pant"),
        Item(2, "Pant"),
        Item(1, "Shirt"),
        Item(1, "Shirt"),
        Item(3, "Tee"),
        Item(3, "Tee"),
        Item(2, "Pant"),
        Item(2, "Pant"),
        Item(1, "Shirt"),
        Item(1, "Shirt"),
        Item(1, "Shirt")
    )
    
    items.groupConsecutiveBy{ left, right -> left.type == right.type }.also(::print)
}
[[Item(type=1, name=Shirt), Item(type=1, name=Shirt)], [Item(type=2, name=Pant), Item(type=2, name=Pant), Item(type=2, name=Pant)], [Item(type=1, name=Shirt), Item(type=1, name=Shirt)], [Item(type=3, name=Tee), Item(type=3, name=Tee)], [Item(type=2, name=Pant), Item(type=2, name=Pant)], [Item(type=1, name=Shirt), Item(type=1, name=Shirt), Item(type=1, name=Shirt)]]
fun <T> Iterable<T>.groupConsecutiveBy(groupIdentifier: (T, T) -> Boolean) =
    if (!this.any())
        emptyList()
    else this
        .drop(1)
        .fold(mutableListOf(mutableListOf(this.first()))) { groups, t ->
            groups.last().apply {
                if (groupIdentifier.invoke(last(), t)) {
                    add(t)
                } else {
                    groups.add(mutableListOf(t))
                }
            }
            groups
        }
val array = intArrayOf(1, 2, 3, 4, 5)
val (even, odd) = array.partition { it % 2 == 0 }
println(even) // [2, 4]
println(odd) // [1, 3, 5]