Home > other >  In Kotlin, How to groupBy only subsequent items?
In Kotlin, How to groupBy only subsequent items?

Time:07-20

I want to groupBy a list of items by its value, but only if subsequent, and ignore grouping otherwise:

input: val values = listOf("Apple", "Apple", "Grape", "Grape", "Apple", "Cherry", "Cherry", "Grape")

output: {"Apple"=2, "Grape"=2, "Apple"=1, "Cherry"=2, "Grape"=1}

CodePudding user response:

You cloud use MultiValueMap which can has duplicated keys. Since there is no native model you should implement yourself or use the open-source library.

Here is a reference.

Map implementation with duplicate keys

CodePudding user response:

There's no built in option for this in Kotlin - it has to be custom, so there are many different options.

Because you need to keep track of the previous element, to compare the current one against, you need to have some sort of state. To achieve this you could use zipWithNext or windowed to group elements. Or use fold and accumulate the values into a list - removing and adding the last element depending on whether there's a break in the sequence.

To try and keep things a bit more clearer (even if it breaks the norms a bit) I recommend using vars and a single loop. I used the buildList { } DSL, which creates a clear scope for the operation.

val result: List<Pair<String, Int>> = buildList {
  var previousElement: String? = null
  var currentCount: Int = 0

  // iterate over each incoming value
  values.forEach { currentElement: String ->

    // currentElement is new - so increment the count
    currentCount  

    // if we have a break in the sequence...
    if (currentElement != previousElement) {
      // then add the current element and count to our output
      add(currentElement to currentCount)
      // reset the count
      currentCount = 0
    }

    // end this iteration - update 'previous'
    previousElement = currentElement
  }
}

Note that result will match the order of your initial list.

  • Related