Concise way of creating a IntRange out of an Int I want to create a collection (in this case a map due to the extended function 'groupBy') that maps an IntRange to a list of a data class, which members are determined whether an int inside the data class is within the IntRange.
The IntRanges are 0..9, 10..19, 20..29, etc.

Concrete example:

data class Trip(
    val (...)
    val distance: Double
) 

[...]

val mappedTrips = trips.groupBy {
    ((it.duration-(it.duration)%10))..((it.duration-(it.duration)%10)+9) }


Explicitly the 

((it.duration-(it.duration)%10))..((it.duration-(it.duration)%10)+9)


part seems to be not very concise, hard to read and therefore I was wondering if there is a way to make it more efficient, meaning more easy to read, concise.

Thank you in advance.

Edit:

TaxiPark Class


package taxipark

data class TaxiPark(
        val allDrivers: Set&lt;Driver&gt;,
        val allPassengers: Set&lt;Passenger&gt;,
        val trips: List&lt;Trip&gt;)

data class Driver(val name: String)
data class Passenger(val name: String)

data class Trip(
        val driver: Driver,
        val passengers: Set&lt;Passenger&gt;,
        // the trip duration in minutes
        val duration: Int,
        // the trip distance in km
        val distance: Double,
        // the percentage of discount (in 0.0..1.0 if not null)
        val discount: Double? = null
) {
    // the total cost of the trip
    val cost: Double
        get() = (1 - (discount ?: 0.0)) * (duration + distance)
}


Task

Find the most frequent trip duration among minute periods 0..9, 10..19, 20..29, and so on.
Return any period if many are the most frequent, return null if there're no trips.

Test sample

class TestTask5TheMostFrequentTripDurationPeriod {

    private fun testDurationPeriod(expected: Set&lt;IntRange?&gt;, tp: TaxiPark) {
        val actual = tp.findTheMostFrequentTripDurationPeriod()
        val message = "Wrong result for 'findTheMostFrequentTripDurationPeriod()': $actual."
        if (expected.size &lt;= 1) {
            Assert.assertEquals(
                    message + tp.display(),
                    expected.firstOrNull(), actual)
        } else {
            Assert.assertTrue(message +
                    tp.display() +
                    "\nPossible results: $expected" +
                    "\nActual: $actual\n",
                    actual?.let { it in expected } ?: expected.isEmpty())
        }
    }

    @Test
    fun test00() = testDurationPeriod(setOf(null), taxiPark(0..1, 0..10))

    @Test
    fun test01() {
        // The period 30..39 is the most frequent since there are two trips (duration 30 and 35)
        testDurationPeriod(setOf(30..39), taxiPark(1..3, 1..5,
                trip(1, 1, duration = 10),
                trip(3, 4, duration = 30),
                trip(1, 2, duration = 20),
                trip(2, 3, duration = 35)))
    }

    @Test
    fun test02() = testDurationPeriod(setOf(30..39), taxiPark(0..5, 0..9,
            trip(0, listOf(2, 9), duration = 14, distance = 25.0),
            trip(1, listOf(8), duration = 39, distance = 37.0, discount = 0.2),
            trip(5, listOf(0, 5), duration = 27, distance = 28.0, discount = 0.3),
            trip(4, listOf(0, 6), duration = 33, distance = 14.0),
            trip(2, listOf(5, 1, 4, 3), duration = 2, distance = 15.0),
            trip(4, listOf(7), duration = 27, distance = 2.0),
            trip(4, listOf(4, 6), duration = 31, distance = 31.0),
            trip(3, listOf(9, 0), duration = 34, distance = 7.0),
            trip(5, listOf(3), duration = 25, distance = 33.0),
            trip(1, listOf(0, 7, 2, 3), duration = 13, distance = 17.0))
    )
}
Since it.duration is quite long, you could use the alternative expression:

(it.duration / 10 * 10) .. (it.duration / 10 * 10 + 9)


You still have common subexpressions, though. To avoid these, you can define a cluster:

fun cluster(x: Double, size: Double) = (x - x % size) .. (x - x % size + size - 1)


or, to avoid the common subexpression:

fun cluster(x: Double, size: Double) = (x - x % size).let { it .. (it + size - 1) }


(I wrote the above without a compiler, so it may or may not work, but you get the idea.)

Then, you can group the trips by their cluster:

trips.groupBy { cluster(it.duration, 10.0) }


By the way, the group "30-39" also contains 39.999, so you might get contacted by a nitpicker that your range should better be called "[30,40)". ;)