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