Is there something in the standard library to perf...
# stdlib
m
Is there something in the standard library to perform a
zip
but with the catch that the second
Iterable
contains a count property to indicate the number of items to consume from the first
Iterable
? Perhaps a running fold can do this, but I can’t quite get my head around it! At the moment, I can get the desired results by separately maintaining an
Iterator
on the first
Iterable
, but this doesn’t feel very clean to me.
Copy code
val list1 = listOf('a', 'b', 'c', 'd', 'e', 'f')
val list2 = listOf(Type2(count = 2), Type2(count = 1), Type2(count = 3))

val expected = listOf(
    Pair(listOf('a', 'b'), Type2(count = 2)),
    Pair(listOf('c'), Type2(count = 1)),
    Pair(listOf('d', 'e', 'f'), Type2(count = 3)),
)

class Type2(val count: Int) {
	...
}
d
If I understand your requirements correctly; you could take advantage of the lazy nature of sequence operations, to efficiently combine a
zip
and
fold
together like this:
Copy code
val inputs = listOf(listOf(1,2,3), listOf(4,5,6,7), listOf(8,9))
val counts = listOf(1, 3, 2)

inputs.asSequence().zip(counts.asSequence(), ::Pair)
    .fold(emptyList<Int>()) { acc, (input, count) ->
        acc + input.take(count)
    }
    .toList()
Output:
Copy code
[1, 4, 5, 6, 8, 9]
m
Thanks @darkmoon_uk but I don’t think that’s what I mean. AFAICT the zip can only work if both sequences are the same length. So I think the first step would be to convert my
list2
by inserting nulls to line it up with
list1
into something like:
listOf(null, Type2(count = 2), Type2(count = 1), null, null, Type2(count = 3))
and then perhaps a
runningFold
over the zipped result. I’ll have a go at this a bit later.
My first attempt using the above idea and
zip
worked but was unnecessarily complex. Here’s my best attempt using `runningFold`: https://pl.kotl.in/ymSbdAybJ
Copy code
val list1 = listOf('a', 'b', 'c', 'd', 'e', 'f')
val list2 = listOf(Type2(2), Type2(1), Type2(3))

val result = list2.runningFold(null as Pair<List<Char>, Type2>? to list1) { (_, remainingChars), type ->
    val chars = remainingChars.take(type.count)
    (chars to type) to remainingChars.drop(type.count)
}.map { it.first }

println(result)
Side note: is there a way to take/drop to a
Pair
? But although it’s a nice little exercise, going with an
Iterator
is way easier: https://pl.kotl.in/ClfI55rEO
Copy code
val list1 = listOf('a', 'b', 'c', 'd', 'e', 'f')
val list2 = listOf(Type2(2), Type2(1), Type2(3))

val list1Iterator = list1.iterator()

val result = list2.map { type ->
    val chars = List(type.count) { list1Iterator.next() }
    chars to type
}

println(result)