n在 Kotlin 中,对具有分组条件的元素进行分组的简洁(最好是功能性)方式是什么?
例如:
class Item(val level : Int)
鉴于列表:(Item(1), Item(2), Item(5))
和两个分组条件:
level > 0 && level < 3level > 4
以下列表是预期的:
listOf(Item(1), Item(2))listOf(Item(5))
该groupBy函数仅接受 1 个条件参数。还有其他有用的功能吗?
n在 Kotlin 中,对具有分组条件的元素进行分组的简洁(最好是功能性)方式是什么?
例如:
class Item(val level : Int)
鉴于列表:(Item(1), Item(2), Item(5))
和两个分组条件:
level > 0 && level < 3level > 4以下列表是预期的:
listOf(Item(1), Item(2))listOf(Item(5))该groupBy函数仅接受 1 个条件参数。还有其他有用的功能吗?
You could return an Int in the lambda passed to groupBy which identifies your criteria. This would work for any number of conditions.
val l = listOf(Item(1), Item(2), Item(5))
val g = l.groupBy {
when {
it.level > 0 && it.level < 3 -> 0
it.level > 4 -> 1
// ...
else -> null
}
}.filterKeys { it != null }) // optional: filter out null as default key
Result:
{0=[Item(level=1), Item(level=2)], 1=[Item(level=5)]}
partion正如已经建议的那样,我也会在这里使用。你也可以链接它们:
val cond1: (Item) -> Boolean = { it.level in 0..2 }
val cond2: (Item) -> Boolean = { it.level > 4 }
val parts = elements
.partition { cond1(it) || cond2(it) }
.first.partition { cond1(it) }
println(parts)
这将导致您的输入迭代效率略低于groupBy. 仍然是线性的运行时复杂度。
尝试filter删除所有不必要的元素,然后删除其中一个groupBy或partition它们,例如:
使用partition(即您只需要 1 个列表中的 2 个):
listSequence()
.filter { it.level > 0 && it.level != 3 } // it seems you are only interested in levels > 0 && != 3
.partition { it.level in 1..2 } // partition into items having 0 < level < 3 and the rest
.run(::println) // prints: [[Item(level=1), Item(level=2)], [Item(level=5)]] (which is a pair of lists)
使用groupBy类似于 Willi Mentzel 所展示的内容:
listSequence()
.filter { it.level > 0 && it.level != 3 } // if you need to filter... otherwise skip that and assign just a random group
.groupBy {
when (it.level) {
in 1..2 -> 0
else -> 1
}
}
.values.run(::println) // which also prints ([Item(level=1), Item(level=2)], [Item(level=5)]) but now is a collection of lists
在这两种情况下,我都使用了如下序列:
fun listSequence() = sequenceOf(Item(1), Item(2), Item(5), Item(-4), Item(0))
取决于您最终要完成的工作...您可能还对其他一些可用的收集功能感兴趣。