# Combine multiple ranges with different resolution

**URL:** <https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822>\
**Category:** New to Julia\
**Tags:** question, syntax\
**Created:** [March 31, 2020, 11:18pm UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822 "2020-03-31T23:18:50Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![baptiste](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baptiste/32/9813_2.png) [@baptiste](https://discourse.julialang.org/u/baptiste)\
**Post date:** [March 31, 2020, 11:18pm UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/1 "2020-03-31T23:18:50Z")

</div>

I’m computing a function that is smooth in some domain and has quite a few fine features somewhere else, so I would like my x variable to have a different resolution in different regions. I’m using `range()` for each subdomain, and while doing my numerical explorations and adjusting those ranges I want the computer to automatically remove duplicates and sort the different ranges without worrying about it myself.

I’ve come up with this, but it feels very clumsy,

```julia
sort(unique(hcat([collect(range(0.3,1,length=100)),
collect(range(1,3,length=500)),
collect(range(1,10,length=100)),
collect(range(10,100,length=100))]...)))

```

Am I missing a more straightforward approach? (in Base Julia – I’m asking this to learn better practice, rather than for the end-result).

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [April 1, 2020, 2:03am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/2 "2020-04-01T02:03:30Z")

</div>

To do explicitly what you want, no. Ranges are basically stored as `(start,stop,steplength)`, so they can’t really be “mixed”.

To address your actual problem, you should consider something like log-spacing. Create a linearly spaced grid, then log transform it. You will get more points closer to zero, and the points at the other end of the grid space out more (because now the growth rate between two points is equal, not the distance between them). You can also apply this transformation as many times as you want.

---

<div class="post-metadata">

**Author:** ![baptiste](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baptiste/32/9813_2.png) [@baptiste](https://discourse.julialang.org/u/baptiste)\
**Post date:** [April 1, 2020, 2:38am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/3 "2020-04-01T02:38:51Z")

</div>

log isn’t really helping because there are various regions of interest requiring high def (sure, I could invent an ad hoc transform). I guess what bothers me is the need to `collect()` each range explicitly just to be able to call unique and sort on the resulting array. **Is there an alternative to `range()` that already expands to an explicit array?**

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 3:02am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/4 "2020-04-01T03:02:01Z")

</div>

Is this what you want? [GitHub - SciML/MultiScaleArrays.jl: A framework for developing multi-scale arrays for use in scientific machine learning (SciML) simulations](https://github.com/SciML/MultiScaleArrays.jl)

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [April 1, 2020, 4:42am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/5 "2020-04-01T04:42:52Z")

</div>

Speed up your original code? That we can do.

You can drop all of the `collect`s. Try this instead.

```julia
sort(unique(Iterators.flatten((range(0.3,1,length=100),
    range(1,3,length=500),
    range(1,10,length=100),
    range(10,100,length=100)))))

```

Many things in Julia just need arguments that are iterable. They don’t need actual arrays.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 1, 2020, 5:23am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/6 "2020-04-01T05:23:01Z")

</div>

> [@baptiste](#):
>
> automatically remove duplicates and sort the different ranges without worrying about it myself

If you are willing to invest a bit more into this, you could make a _partition_ of n adjacent ranges by storing n+1 endpoints and n lengths. This should be easy to code in a custom type, and you can reuse a lot of optimized code for ranges (eg `searchsortedfirst` for locating bins).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 1, 2020, 6:43am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/7 "2020-04-01T06:43:59Z")

</div>

> [@baptiste](#):
>
> ```julia
> sort(unique(hcat([collect(range(0.3,1,length=100)), 
> collect(range(1,3,length=500)), 
> collect(range(1,10,length=100)), 
> collect(range(10,100,length=100))]...)))
> 
> ```

There are a few things wrong with this code.

Firstly, I guess you mean `vcat` not `hcat`, since `hcat` will try to do horizontal concatenation and create a matrix. It will actually error here.

Secondly, you put each range in a vector and then splat that vector, like this:

```julia
vcat([a, b, c]...)

```

This is identical to writing

```julia
vcat(a, b, c)

```

except that it creates a temporary array for no reason that you just throw away again, and which reduces performance and increases allocations.

Thirdly, you are using `collect`, which you should basically never do. `collect` is a function you should rarely need to use, and certainly not here, it just takes a fast, lightweight, cheap, smart range-vector, and turns it into a heavy, expensive and dumb vector.

So re-writing your code:

```julia
sort(unique(vcat(range(0.3,1,length=100),
                 range(1,3,length=500),
                 range(1,10,length=100),
                 range(10,100,length=100))))

```

There are still probably better ways of doing what you want.

Rule of thumb: Don’t use `collect`. Only use it if your code fails otherwise.

**Edit:** You can also write `[a; b; c]` instead of `vcat(a, b, c)` if you prefer. They are the same thing.

---

<div class="post-metadata">

**Author:** ![baptiste](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baptiste/32/9813_2.png) [@baptiste](https://discourse.julialang.org/u/baptiste)\
**Post date:** [April 1, 2020, 7:09am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/8 "2020-04-01T07:09:36Z")

</div>

Thanks – indeed, `collect()` struck me as something to be avoided, but since I was wrongly using hcat\* instead of vcat I mistakenly assumed I needed to explicitly expand the ranges before combining them.

It often seems obvious in hindsight, but not when typing new things in a new language.

\*: (Though by some unfortunate coincidence my code with hcat did work – all the ranges had the same number of elements in my original example)

---

<div class="post-metadata">

**Author:** ![baptiste](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baptiste/32/9813_2.png) [@baptiste](https://discourse.julialang.org/u/baptiste)\
**Post date:** [April 1, 2020, 7:14am UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/9 "2020-04-01T07:14:57Z")

</div>

True, I can imagine a few ways to abstract this problem out, but here I really wanted to clarify my understanding of those low-level basic functions. Thanks, though.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [April 1, 2020, 6:31pm UTC](https://discourse.julialang.org/t/combine-multiple-ranges-with-different-resolution/36822/10 "2020-04-01T18:31:08Z")

</div>

In the spirit of premature optimization, I tried to eliminate allocations for you by defining an iterator that is equivalent to `range` when `collect`ed. Surprisingly, it doesn’t appear to be faster when you substitute it into your problem, but there could be some benchmarking trickery going on.

```julia
linspace(a,b,N)= (a+ (b-a)*(i)/(N-1) for i=0:(N-1))

```

You could play around with it though.
