Is there an elegant way to split a list of Person ...
# getting-started
k
Is there an elegant way to split a list of Person for every 10 persons and return a list of object Group(persons(10 or less/rest))?
d
you mean chunked()?
w
a quickly test to prove it:
Copy code
@Test
    fun `test chunked`() {
        val list =
                List(99) { it }
        val result = list.chunked(10)

        println(result)

        assertEquals(10, result.size)
        assertEquals(10, result[0].size)
        assertEquals(10, result[1].size)
        assertEquals(10, result[2].size)
        assertEquals(10, result[3].size)
        assertEquals(10, result[4].size)
        assertEquals(10, result[5].size)
        assertEquals(10, result[6].size)
        assertEquals(10, result[7].size)
        assertEquals(10, result[8].size)
        assertEquals(9, result[9].size)
    }
k
Copy code
val groups = persons.chunked(10, { Group(it) })
I get Lambda argument should be moved out of parentheses
d
not that it should be, but yeah it's better
val groups = persons.chunked(10) { Group(it) }
k
Thanks! Chunked is just what I was looking for
When I chunk 50, I get 36
Is there a reason why?
d
what do you mean?
m
If there are fewer than
size
elements left in the list, then the chunk will have that amount of elements.
k
All of the lists (so far I have seen) has a length of 36
d
can you post some code here?
w
Is that not something your
Group
is doing?
k
Copy code
listOf220KElements.chunked(50) { Domain.ApiRequest(it, Config.SOURCE, Config.API_KEY) }
w
😱 It is weird:
Copy code
data class Group(val values: List<Int>)

    @Test
    fun `test group chunked`() {
        val list = List(99) { it }
        val result = list.chunked(10) { Group(it) }

        println(result)

        assertEquals(10, result.size)
        assertEquals(10, result[0].values.size)
        assertEquals(10, result[1].values.size)
        assertEquals(10, result[2].values.size)
        assertEquals(10, result[3].values.size)
        assertEquals(10, result[4].values.size)
        assertEquals(10, result[5].values.size)
        assertEquals(10, result[6].values.size)
        assertEquals(10, result[7].values.size)
        assertEquals(10, result[8].values.size)
        assertEquals(9, result[9].values.size)
    }

    @Test
    fun `test chunked`() {
        val list = List(99) { it }
        val result = list.chunked(10)

        println(result)

        assertEquals(10, result.size)
        assertEquals(10, result[0].size)
        assertEquals(10, result[1].size)
        assertEquals(10, result[2].size)
        assertEquals(10, result[3].size)
        assertEquals(10, result[4].size)
        assertEquals(10, result[5].size)
        assertEquals(10, result[6].size)
        assertEquals(10, result[7].size)
        assertEquals(10, result[8].size)
        assertEquals(9, result[9].size)
    }
the
test group chunked
, some of the expected size 10 actually came as 9!!!!
Oh wait, it is something wrong here.
[Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98])]
k
Copy code
* Splits this collection into several lists each not exceeding the given [size]
 * and applies the given [transform] function to an each.
So it is anything less than size
w
I believe is this part of the docs:
Copy code
* Note that the list passed to the [transform] function is ephemeral and is valid only inside that function.
 * You should not store it or allow it to escape in some way, unless you made a snapshot of it.
 * The last list may have less elements than the given [size].
Copy code
data class Group(val values: List<Int>)

    @Test
    fun `test group chunked`() {
        val list = List(99) { it }
        val result = list.chunked(10) { Group(listOf(*it.toTypedArray())) }

        println(result)

        assertEquals(10, result.size)
        assertEquals(10, result[0].values.size)
        assertEquals(10, result[1].values.size)
        assertEquals(10, result[2].values.size)
        assertEquals(10, result[3].values.size)
        assertEquals(10, result[4].values.size)
        assertEquals(10, result[5].values.size)
        assertEquals(10, result[6].values.size)
        assertEquals(10, result[7].values.size)
        assertEquals(10, result[8].values.size)
        assertEquals(9, result[9].values.size)
    }
this nows works fine, as expected.
Giving
[Group(values=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), Group(values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]), Group(values=[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]), Group(values=[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]), Group(values=[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]), Group(values=[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]), Group(values=[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]), Group(values=[70, 71, 72, 73, 74, 75, 76, 77, 78, 79]), Group(values=[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]), Group(values=[90, 91, 92, 93, 94, 95, 96, 97, 98])]
m
Oh wow, that part about the ephemeral list in the transform function kind of feels like a trap. I think I would have written it like this then:
Copy code
list.asSequence()
    .chunked(10)
    .map { Group(it) }
w
You can run some performance tests on it, looks like your list could be really big, maybe doing inside the
chunked
will be faster (I believe it will be doing in the same time it loops through the list), anyway, maybe is worth to check it too.