JPV
JPV

Reputation: 1079

Kotlin functional find single element

I am relatively new to Kotlin and I try to overcome a special case. I am filtering a books store and want to verify that the length of the obtained list is exactly one unit shorter than the original one. Further I need to verify that the discarded element is under a specific state. Here is my example:

  fun BookStoreVerified(bookStore: BookStore): Boolean {

    val specialChapter = bookStore.stores
      .flatMap { it.books }
      .flatMap { it.chapters }.filter { it != null && it.state == Chapter.SPECIAL }

    val total = bookStore.stores
      .flatMap { it.books }
      .flatMap { it.chapters }
      .filterNotNull()

   val finalChapters = book.stores
      .flatMap { it.books }
      .flatMap { it.chapters }
      .filter { it != null && it.state.isCorrect }

    return (finalChapters.size + specialChapterFigure.size == total.size) && (specialChapter.size == 1)
  }

My question is if there is a smarter way to compute the above operation. I would like to know if ander a scope like filter, map can we make reference to the previous object? ( get the length of the original list for instance ?)

Upvotes: 0

Views: 171

Answers (1)

David Soroko
David Soroko

Reputation: 9086

You have Books where each Book contains a list of Chapters. You want to partition chapters from all the books according to some criteria.

With this in mind the partition function can be useful:

data class Chapter(val state: String)
data class Book(val chapters: List<Chapter>? = null)

fun main() {

    val books = listOf(
        Book(),
        Book(chapters = listOf(Chapter("a"), Chapter("SPECIAL"))),
        Book(chapters = listOf(Chapter("c"), Chapter("d")))
    )

    val (specialChs, regularChs) = books
        .flatMap { it.chapters ?: emptyList() }
        .partition { it.state == "SPECIAL" }


    println(specialChs) // [Chapter(state=SPECIAL)]
    println(regularChs) // [Chapter(state=a), Chapter(state=c), Chapter(state=d)]
}

Now that you have specialChs and regularChs, you can check whatever invariants you want.

For example:

check(specialChs.size == 1 && specialChs.first().state == 
"SPECIAL")

Edit: It is possible to abstract away the existence of null chapters inside a Book:

data class Book(val chapters: List<Chapter>? = null) {
    val safeChapters: List<Chapter>
        get() = chapters ?: emptyList()
}

then in your code you can flatMap { it.safeChapters } instead of .flatMap { it.chapters ?: emptyList() }

Upvotes: 1

Related Questions