Garamuro
Garamuro

Reputation: 25

Kotlin: Get Values of a Range in another Range

Hello im trying to write a function that compares to ranges and returns the value of the first range in the second.

Example : Range A is (22.0..24.0) Range B ( 20.0..26.0)

so in that case the return value should be 2.0

if Range B is (23.0..26.0) it should return 1.0

How can i do this?

Upvotes: 1

Views: 2528

Answers (3)

gidds
gidds

Reputation: 18557

What you're doing here is taking the intersection (overlap) of two ranges, and calculating its size.  So, building on what Adam Millerchip and cactustictacs have already done, I think I'd break the problem down into simpler parts: min, max, and size properties for a range, and an intersect function that calculates the common subrange of two ranges (if there is one):

val ClosedFloatingPointRange<Double>.min
    get() = minOf(start, endInclusive)

val ClosedFloatingPointRange<Double>.max
    get() = maxOf(start, endInclusive)

val ClosedFloatingPointRange<Double>.size
    get() = max - min

infix fun ClosedFloatingPointRange<Double>.intersect(other: ClosedFloatingPointRange<Double>)
    = if (min <= other.max && other.min <= max)
        maxOf(min, other.min).rangeTo(minOf(max, other.max))
    else
        null

With those, you can do e.g.:

val a = 22.0 .. 24.0
val b = 20.0 .. 26.0

println(a intersect b)
println((a intersect b)?.size)

Having the size explicit and separate from the intersection makes each one easier to understand, easier to test, and easier to reuse.  And having intersect return null if there's no overlap is safer.

(This should work for negative numbers and for descending ranges; the intersection is always given as ascending.  This assumes Double ranges; it could be made to handle other types too, though the type parameters get messy.)

TBH, I'm a little surprised that none of those are in the standard library…

Upvotes: 3

Ananiya J. Kesto
Ananiya J. Kesto

Reputation: 1364

Ok well Range some what act as a list so the the could do like

val r1 = (22.0)..(25.0)
val r2 = (23.0)..(30.0)
val findRangeOfFirstElement = (r1.start -r2.start)

Upvotes: -1

Adam Millerchip
Adam Millerchip

Reputation: 23091

You could write a function like this:

fun ClosedRange<Double>.containedIn(other: ClosedRange<Double>) =
    (min(endInclusive, other.endInclusive) - max(start, other.start))
        .coerceAtLeast(0.0)

And then use it like this:

val rangeA = 22.0..24.0
val rangeB = 20.0..26.0
val rangeC = 23.0..26.0

println(rangeA.containedIn(rangeB))
println(rangeA.containedIn(rangeC))

Result:

2.0
1.0

Note: you should also import the min/max functions:

import kotlin.math.max
import kotlin.math.min

Upvotes: 5

Related Questions