Mapping a value from one range to another

I have two ranges a and b.

a = 1:10
b = 1:100

I have a value from a, say 5. If I were to map it onto range b its equivalent would be 50. In python you can write a function that does this like this:

def map_range(range1: tuple, range2: tuple, val):
    slope = (range2[1] - range2[0]) / (range1[1] - range1[0])
    return range2[0] + slope * (val - range1[0])

With the more unique way julia handles ranges I was wondering if it has a better method of doing something like this?

you can decide what the edge case behavior you want, but this should do what you want in case of divisible ranges


julia> function map_range(range1, range2, val)
           slope = length(range2)Ć·length(range1)
           return range2[findfirst(==(val), range1) * slope]
       end
map_range (generic function with 1 method)

julia> map_range(1:10, 1:100, 6)
60

julia> map_range(1:10, 1:100, 5)
50

julia> map_range(1:20, 1:100, 5)
25

julia> map_range(1:20, 1:100, 10)
50

What do you mean by divisible ranges? Any two ranges that can be divided, or like divided evenly?

your python function would map val into values that didnā€™t exist in the second range, a:b in Julia by default has unit step

1 Like

This oneā€™s really confusing. For those two ranges slope would be equal to 1.0. So 5 would map to 5.0. But you say it maps to 50?

in python they pass (start, end) tuple as ā€œrangeā€

I thought they used range(start, stop) or something.

I guess I was confused by the use of the word ā€˜rangeā€™, and the reference to 1:10. The OP actually isnā€™t asking about ranges at all, but tuples, both in Python and Julia.

julia> function map_ranges(t1 ::Tuple, t2::Tuple, val)
           r1=range(t1...)
           r2=range(t2...,length(r1))
           return r2[val]
       end
map_ranges (generic function with 2 methods)

julia> map_ranges((1,10),(2,37),1)
2.0

julia> map_ranges((1,10),(2,37),10)
37.0

julia> map_ranges((1,10),(2,37),7)
25.333333333333332

This scheme seems to me more adherent to the Python version and responds to the expectation that the same mapping can be done in Julia in a more ā€œsimpleā€ way

In my opinion, itā€™s as you say! As I wrote without using the linear transformation formula, which is implicitly realized by the length parameter of range(start, stop, length).
Being a linear mapping, it needs to be verified (only) in two distinct points (only one straight line passes through two points :smile:).


1--> 1
10--> 100

The reason you get 45 is that in python the same range would be 0 to 100 (not including the end). Yes, the python version uses tuples because using actual ranges in python would be impractical. I was wondering if there was a better way to do it in julia. Using actual ranges is more readable imo.

To me it looks like ranges are the wrong concept for this. Arenā€™t you actually looking for an interval. Ranges donā€™t just have a start and a stop, but a steplength or resolution as well. It doesnā€™t make sense to me to say that 1:10 vs 1:100 maps 5 to 50. This makes more sense for intervals (though it should be [0, 10] and [0, 100]).

Tuples are more suited to describing intervals than ranges are.

1 Like

It is not clear to me if this mapping is what you are looking for.


julia> map_range(1:10, 1:50, 1)
5

julia> map_range(1:10, 1:100, 1)
10

julia> map_range(0:10, 0:50, 1)
7