Kotlin:将大列表转换为设置分区大小的子列表
我正在寻找一个与之等效的函数,它可以将一个大的列表分成若干批进行处理。我确实看到了哪些可以被改编成类似的功能,但我想检查并确保我没有错过一个内置的或疯狂的简单替代方案,而不是自己的功能。注意:对于Kotlin 1.2及更新版本,请参阅标准库中的和功能。不需要定制解决方案Kotlin:将大列表转换为设置分区大小的子列表,kotlin,Kotlin,我正在寻找一个与之等效的函数,它可以将一个大的列表分成若干批进行处理。我确实看到了哪些可以被改编成类似的功能,但我想检查并确保我没有错过一个内置的或疯狂的简单替代方案,而不是自己的功能。注意:对于Kotlin 1.2及更新版本,请参阅标准库中的和功能。不需要定制解决方案 这里是一个延迟批处理扩展函数的实现,它将获取一个集合,或任何可以成为序列的对象,并返回一个序列列表的序列,最后一个是该大小或更小的值 将列表迭代为批的示例用法: myList.asSequence().batch(5).for
这里是一个延迟批处理扩展函数的实现,它将获取一个集合,或任何可以成为
序列的对象,并返回一个序列列表的序列,最后一个是该大小或更小的值
将列表迭代为批的示例用法:
myList.asSequence().batch(5).forEach { group ->
// receive a Sequence of size 5 (or less for final)
}
将列表
批次转换为集合
的示例:
myList.asSequence().batch(5).map { it.toSet() }
请参阅下面的第一个测试用例,以显示给定特定输入的输出
函数的代码序列。批处理(groupSize)
:
public fun <T> Sequence<T>.batch(n: Int): Sequence<List<T>> {
return BatchingSequence(this, n)
}
private class BatchingSequence<T>(val source: Sequence<T>, val batchSize: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
val iterate = if (batchSize > 0) source.iterator() else emptyList<T>().iterator()
override fun computeNext() {
if (iterate.hasNext()) setNext(iterate.asSequence().take(batchSize).toList())
else done()
}
}
}
class TestGroupingStream {
@Test fun testConvertToListOfGroupsWithoutConsumingGroup() {
val listOfGroups = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asSequence().batch(2).toList()
assertEquals(5, listOfGroups.size)
assertEquals(listOf(1,2), listOfGroups[0].toList())
assertEquals(listOf(3,4), listOfGroups[1].toList())
assertEquals(listOf(5,6), listOfGroups[2].toList())
assertEquals(listOf(7,8), listOfGroups[3].toList())
assertEquals(listOf(9,10), listOfGroups[4].toList())
}
@Test fun testSpecificCase() {
val originalStream = listOf(1,2,3,4,5,6,7,8,9,10)
val results = originalStream.asSequence().batch(3).map { group ->
group.toList()
}.toList()
assertEquals(listOf(1,2,3), results[0])
assertEquals(listOf(4,5,6), results[1])
assertEquals(listOf(7,8,9), results[2])
assertEquals(listOf(10), results[3])
}
fun testStream(testList: List<Int>, batchSize: Int, expectedGroups: Int) {
var groupSeenCount = 0
var itemsSeen = ArrayList<Int>()
testList.asSequence().batch(batchSize).forEach { groupStream ->
groupSeenCount++
groupStream.forEach { item ->
itemsSeen.add(item)
}
}
assertEquals(testList, itemsSeen)
assertEquals(groupSeenCount, expectedGroups)
}
@Test fun groupsOfExactSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15), 5, 3)
}
@Test fun groupsOfOddSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18), 5, 4)
testStream(listOf(1,2,3,4), 3, 2)
}
@Test fun groupsOfLessThanBatchSize() {
testStream(listOf(1,2,3), 5, 1)
testStream(listOf(1), 5, 1)
}
@Test fun groupsOfSize1() {
testStream(listOf(1,2,3), 1, 3)
}
@Test fun groupsOfSize0() {
val testList = listOf(1,2,3)
val groupCountZero = testList.asSequence().batch(0).toList().size
assertEquals(0, groupCountZero)
val groupCountNeg = testList.asSequence().batch(-1).toList().size
assertEquals(0, groupCountNeg)
}
@Test fun emptySource() {
listOf<Int>().asSequence().batch(1).forEach { groupStream ->
fail()
}
}
}
public-fun-Sequence.batch(n:Int):序列{
返回批处理顺序(此,n)
}
私有类BatchingSequence(val源:序列,val batchSize:Int):序列{
重写有趣的迭代器():迭代器=对象:AbstractIterator(){
val iterate=if(batchSize>0)source.iterator()else emptyList().iterator()
重写computeNext(){
if(iterate.hasNext())setNext(iterate.asSequence().take(batchSize.toList())
否则完成()
}
}
}
证明其有效的单元测试:
public fun <T> Sequence<T>.batch(n: Int): Sequence<List<T>> {
return BatchingSequence(this, n)
}
private class BatchingSequence<T>(val source: Sequence<T>, val batchSize: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
val iterate = if (batchSize > 0) source.iterator() else emptyList<T>().iterator()
override fun computeNext() {
if (iterate.hasNext()) setNext(iterate.asSequence().take(batchSize).toList())
else done()
}
}
}
class TestGroupingStream {
@Test fun testConvertToListOfGroupsWithoutConsumingGroup() {
val listOfGroups = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asSequence().batch(2).toList()
assertEquals(5, listOfGroups.size)
assertEquals(listOf(1,2), listOfGroups[0].toList())
assertEquals(listOf(3,4), listOfGroups[1].toList())
assertEquals(listOf(5,6), listOfGroups[2].toList())
assertEquals(listOf(7,8), listOfGroups[3].toList())
assertEquals(listOf(9,10), listOfGroups[4].toList())
}
@Test fun testSpecificCase() {
val originalStream = listOf(1,2,3,4,5,6,7,8,9,10)
val results = originalStream.asSequence().batch(3).map { group ->
group.toList()
}.toList()
assertEquals(listOf(1,2,3), results[0])
assertEquals(listOf(4,5,6), results[1])
assertEquals(listOf(7,8,9), results[2])
assertEquals(listOf(10), results[3])
}
fun testStream(testList: List<Int>, batchSize: Int, expectedGroups: Int) {
var groupSeenCount = 0
var itemsSeen = ArrayList<Int>()
testList.asSequence().batch(batchSize).forEach { groupStream ->
groupSeenCount++
groupStream.forEach { item ->
itemsSeen.add(item)
}
}
assertEquals(testList, itemsSeen)
assertEquals(groupSeenCount, expectedGroups)
}
@Test fun groupsOfExactSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15), 5, 3)
}
@Test fun groupsOfOddSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18), 5, 4)
testStream(listOf(1,2,3,4), 3, 2)
}
@Test fun groupsOfLessThanBatchSize() {
testStream(listOf(1,2,3), 5, 1)
testStream(listOf(1), 5, 1)
}
@Test fun groupsOfSize1() {
testStream(listOf(1,2,3), 1, 3)
}
@Test fun groupsOfSize0() {
val testList = listOf(1,2,3)
val groupCountZero = testList.asSequence().batch(0).toList().size
assertEquals(0, groupCountZero)
val groupCountNeg = testList.asSequence().batch(-1).toList().size
assertEquals(0, groupCountNeg)
}
@Test fun emptySource() {
listOf<Int>().asSequence().batch(1).forEach { groupStream ->
fail()
}
}
}
class TestGroupingStream{
@Test fun TestConvertToListofGroup SwithOutConsumingGroup()测试乐趣{
val listOfGroups=listOf(1,2,3,4,5,6,7,8,9,10).asSequence().batch(2).toList()
assertEquals(5,组列表大小)
assertEquals(listOf(1,2),ListofGroup[0].toList())
assertEquals(listOf(3,4),ListofGroup[1].toList())
assertEquals(listOf(5,6),ListofGroup[2].toList())
assertEquals(listOf(7,8),ListofGroup[3].toList())
assertEquals(listOf(9,10),ListofGroup[4].toList())
}
@测试乐趣testSpecificCase(){
val originalStream=列表(1,2,3,4,5,6,7,8,9,10)
val results=originalStream.asSequence().batch(3).map{group->
toList()组
}托利斯先生()
assertEquals(列表(1,2,3),结果[0])
资产质量(列表(4,5,6),结果[1])
资产质量(列表(7,8,9),结果[2])
资产质量(列表(10),结果[3])
}
有趣的testStream(testList:List,batchSize:Int,expectedGroups:Int){
var groupSeenCount=0
var itemssen=ArrayList()
testList.asSequence().batch(batchSize).forEach{groupStream->
groupSeenCount++
groupStream.forEach{item->
项目SEEN.add(项目)
}
}
assertEquals(测试列表、项目SEN)
assertEquals(groupSeenCount、expectedGroups)
}
@测试组精确大小(){
测试流(列表(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),5,3)
}
@测试乐趣组OddSize(){
测试流(列表(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18),5,4)
testStream(listOf(1,2,3,4),3,2)
}
@测试组小于BatchSize(){
testStream(listOf(1,2,3),5,1)
testStream(listOf(1),5,1)
}
@测试组大小1(){
testStream(listOf(1,2,3),1,3)
}
@测试乐趣组大小0(){
val testList=listOf(1,2,3)
val groupCountZero=testList.asSequence().batch(0.toList().size
assertEquals(0,groupCountZero)
val groupCountNeg=testList.asSequence().batch(-1).toList().size
assertEquals(0,groupCountNeg)
}
@TestFunEmptySource(){
listOf().asSequence().batch(1).forEach{groupStream->
失败()
}
}
}
在Kotlin 1.2 M2及更高版本中,您可以使用和(请参阅)。请注意,也存在序列
差异(请参阅)
对于1.2 M2之前的Kotlin版本,我建议使用谷歌番石榴
(它使用):
如果您不熟悉,请参阅以了解更多详细信息
如果需要,您可以为其创建自己的Kotlin:
fun <T> List<T>.collate(size: Int): List<List<T>> = Lists.partition(this, size)
或
fun List.collate(大小:Int):序列{
需要(大小>0)
返回if(isEmpty()){
空序列
}否则{
(0..lastIndex/size).asSequence().map{
val fromIndex=it*大小
val toIndex=Math.min(fromIndex+size,this.size)
子列表(从索引到索引)
}
}
}
一个更简单/功能化的解决方案是
val items = (1..100).map { "foo_${it}" }
fun <T> Iterable<T>.batch(chunkSize: Int) =
withIndex(). // create index value pairs
groupBy { it.index / chunkSize }. // create grouping index
map { it.value.map { it.value } } // split into different partitions
items.batch(3)
val items=(1..100).map{“foo{it}”
有趣的Iterable.batch(chunkSize:Int)=
withIndex()。//创建索引值对
groupBy{it.index/chunkSize}.//创建分组索引
map{it.value.map{it.value}}//拆分为不同的分区
项目。批次(3)
注1:我个人更喜欢将partition
作为这里的方法名,但Kotlin已经给出了一个谓词,将列表分成两部分
注2:Jayson的迭代器解决方案在大型集合中的扩展性可能比此解决方案更好。不幸的是,目前还没有内置函数,而其他答案中基于函数和序列的实现看起来不错,如果您只需要列表的列表
,我建议写一些难看的、命令式的、但性能良好的代码
这是我的最终结果:
fun <T> List<T>.batch(chunkSize: Int): List<List<T>> {
if (chunkSize <= 0) {
throw IllegalArgumentException("chunkSize must be greater than 0")
}
val capacity = (this.size + chunkSize - 1) / chunkSize
val list = ArrayList<ArrayList<T>>(capacity)
for (i in 0 until this.size) {
if (i % chunkSize == 0) {
list.add(ArrayList(chunkSize))
}
list.last().add(this.get(i))
}
return list
}
fun List.batch(chunkSize:Int):List{
如果(chunkSize使用Kotlin 1.3,根据您的需要,您可以选择以下方法之一来解决您的问题
#1.使用
#2.使用
虚拟阵列
使用:
显然,这可以使其不懒惰,例如映射到fun <T> List<T>.batch(chunkSize: Int): List<List<T>> {
if (chunkSize <= 0) {
throw IllegalArgumentException("chunkSize must be greater than 0")
}
val capacity = (this.size + chunkSize - 1) / chunkSize
val list = ArrayList<ArrayList<T>>(capacity)
for (i in 0 until this.size) {
if (i % chunkSize == 0) {
list.add(ArrayList(chunkSize))
}
list.last().add(this.get(i))
}
return list
}
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.chunked(2)
//val newList = list.chunked(size = 2) // also works
print(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.windowed(2, 2, true)
//val newList = list.windowed(size = 2, step = 2, partialWindows = true) // also works
println(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
for (i in 0..49){
var data="java"
}
array.add(data)
var data=array?.chunked(15)