# Is there a function for creating n (nearly) evenly-spaced integers for indexing?

**URL:** <https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744>\
**Category:** New to Julia\
**Tags:** indexing\
**Created:** [January 12, 2024, 8:07pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744 "2024-01-12T20:07:31Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 13, 2024, 9:48pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/21 "2024-01-13T21:48:23Z")

</div>

This seems to be different from the OP example, as it produces indexes: `1:3:88`, and not variable step (= 3 or 4) indexes.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [January 13, 2024, 10:06pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/22 "2024-01-13T22:06:46Z")

</div>

From the proposed solutions I seemed to understand that this was the expected result.

```julia
A=rand(100)
A[range(begin, step=end ÷ len, length=len)]

```

It is not so?  
I just wanted to write one of the solutions a little differently

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 13, 2024, 10:16pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/23 "2024-01-13T22:16:34Z")

</div>

Let’s say I want an integer difference between integers, and I care that that each `step` between each number is an integer. Julia has a convenient syntax for this: `begin:step:end`.

My criterion may be distinct from yours.

1. I want my indices to be exactly spaced apart by the same `step`.
2. I do not care if the last index is included.

```julia-repl
julia> function helper(A; step)
           B = A[begin:step:end]
           @info "B = A[begin:step:end]" B[1] B[2] B[end] length(B)
           return B
       end
helper (generic function with 1 method)

julia> A = 1:100
1:100

julia> helper(A, step = 1)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 2
│ B[end] = 100
└ length(B) = 100
1:1:100

julia> helper(A, step = 2)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 3
│ B[end] = 99
└ length(B) = 50
1:2:99

julia> helper(A, step = 3)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 4
│ B[end] = 100
└ length(B) = 34
1:3:100

julia> helper(A, step = 4)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 5
│ B[end] = 97
└ length(B) = 25
1:4:97

julia> helper(A, step = 5)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 6
│ B[end] = 96
└ length(B) = 20
1:5:96

julia> helper(A, step = 6)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 7
│ B[end] = 97
└ length(B) = 17
1:6:97

julia> helper(A, step = 7)
┌ Info: B = A[begin:step:end]
│ B[1] = 1
│ B[2] = 8
│ B[end] = 99
└ length(B) = 15
1:7:99

```

For many arrays, `1:step:end` might do, but not all Julia arrays start at index `1`.

Next we need to determine `step`. It could be `length(A) ÷ desired_length`. Note that `÷` is an alias for `div`, which will do integer division, rounding towards zero. `÷` is similar to `\\` in Python.

Simply setting `step` as above would create an array that is longer than desired. Thus we have to further truncate the result to the desired length.

Below I will use the idiom `end-begin+1` to stand in for `length`.

```julia-repl
julia> function helper2(A; length)
           B = A[begin:(end-begin+1)÷length:end]
           B = B[begin:begin+length-1]
           @info "B:" B[1] B[2] B[end] Base.length(B)
           return B
       end
helper2 (generic function with 1 method)

julia> helper2(A, length = 100)
┌ Info: B:
│ B[1] = 1
│ B[2] = 2
│ B[end] = 100
└ Base.length(B) = 100
1:1:100

julia> helper2(A, length = 95)
┌ Info: B:
│ B[1] = 1
│ B[2] = 2
│ B[end] = 95
└ Base.length(B) = 95
1:1:95

julia> helper2(A, length = 50)
┌ Info: B:
│ B[1] = 1
│ B[2] = 3
│ B[end] = 99
└ Base.length(B) = 50
1:2:99

julia> helper2(A, length = 45)
┌ Info: B:
│ B[1] = 1
│ B[2] = 3
│ B[end] = 89
└ Base.length(B) = 45
1:2:89

julia> helper2(A, length = 32)
┌ Info: B:
│ B[1] = 1
│ B[2] = 4
│ B[end] = 94
└ Base.length(B) = 32
1:3:94

julia> helper2(A, length = 16)
┌ Info: B:
│ B[1] = 1
│ B[2] = 7
│ B[end] = 91
└ Base.length(B) = 16

```

In summary, if you are flexible on the last index but want an integer step, there is an easy syntax if you can specify `step`.

---

<div class="post-metadata">

**Author:** ![parb](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@parb](https://discourse.julialang.org/u/parb)\
**Post date:** [January 15, 2024, 2:41pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/24 "2024-01-15T14:41:21Z")

</div>

Great idea

---

<div class="post-metadata">

**Author:** ![parb](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@parb](https://discourse.julialang.org/u/parb)\
**Post date:** [January 15, 2024, 2:57pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/25 "2024-01-15T14:57:16Z")

</div>

Thank you for your help! I like you and @rocco_sprmnt21 using the `div` function, though I haven’t quite made it work.

I tried

```julia
helper2(1:41, 23)

```

and got back `1:1:23`. This would downsample the long array but instead give only the first section of it.

---

<div class="post-metadata">

**Author:** ![parb](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@parb](https://discourse.julialang.org/u/parb)\
**Post date:** [January 15, 2024, 3:15pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/26 "2024-01-15T15:15:59Z")

</div>

This is very similar to @mbauman’s solution - which is equally good. I slightly prefer using `div` rather than `round` (and rather than `÷` which I can’t find on my keyboard).

So in the original notation, from now on I’ll use

```julia
sampleindices = range(start=1, step=div(length(longarray), numsamples), length=numsamples)
downsampled = longarray[sampleindices]

```

The reason for making `sampleindices` is that other parallel arrays need indexing my typical use cases.

Thank you everyone!

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 15, 2024, 3:44pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/27 "2024-01-15T15:44:21Z")

</div>

In one case (round) the range 1:100 is sampled with variable step (3 or 4) but does cover the full interval from 1 to 100, while in the simpler/trivial case, a constant step of 3 is used to produce 30 indexes: 1:3:88, leaving a big gap in the tail (from 89 to 100).

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [January 15, 2024, 3:54pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/28 "2024-01-15T15:54:48Z")

</div>

> [@parb](#):
>
> and rather than `÷` which I can’t find on my keyboard)

```julia
help?> ÷
"÷" can be typed by \div<tab>

```

---

<div class="post-metadata">

**Author:** ![parb](https://avatars.discourse-cdn.com/v4/letter/p/4da419/32.png) [@parb](https://discourse.julialang.org/u/parb)\
**Post date:** [January 15, 2024, 4:04pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/29 "2024-01-15T16:04:26Z")

</div>

These are important nuances to keep in mind for each use case! I’d mark both as solutions if I could.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 15, 2024, 7:09pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/30 "2024-01-15T19:09:00Z")

</div>

I wrote a more general function for similar usecases:

```julia
julia> using DataManipulation

julia> discreterange(identity, 1, 100; length=30)
30-element Vector{Int64}:
   1
   4
   8
...
  90
  93
  97
 100

```

Its main target are transformed ranges, like logarithmically-spaced `discreterange(log, 1, 1000; length=30)`. There, you cannot just create a float range and round it to integers.  
But `discreterange` works for regular linear ranges as well, as shown in the example.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 15, 2024, 7:37pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/31 "2024-01-15T19:37:31Z")

</div>

> [@aplavin](#):
>
> discreterange(log, 1, 1000; length=30)

I noticed that the initial indexes don’t really follow a logarithmic proportion.  
In this specific example, the output is equivalent to:

```julia-auto
[1:4; round.(Int, exp.(range(log(5), log(1000), length=30-4)))]

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 15, 2024, 9:56pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/32 "2024-01-15T21:56:57Z")

</div>

> [@rafael.guerra](#):
>
> I noticed that the initial indexes don’t really follow a logarithmic proportion.

Of course, because that would be impossible (:

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 15, 2024, 10:06pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/33 "2024-01-15T22:06:16Z")

</div>

> [@aplavin](#):
>
> impossible (:

In some applications, it makes sense to allow repeated indexes at the beginning:

```julia-auto
round.(Int, exp.(range(log(1), log(1000), length=30)))

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 15, 2024, 10:20pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/34 "2024-01-15T22:20:51Z")

</div>

Sure, the whole point of `discreterange()` is to give distinct integers. So both variants are available, either for regular linear ranges of for mapped ones:

```julia
julia> round.(Int, maprange(log, 1, 100; length=20))
[1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 14, 18, 23, 30, 38, 48, 62, 78, 100]

julia> discreterange(log, 1, 100; length=20)
[1, 2, 3, 4, 5, 6, 7, 9, 11, 14, 17, 20, 25, 30, 37, 45, 55, 67, 82, 100]

```

---

<div class="post-metadata">

**Author:** ![apo383](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/apo383/32/11272_2.png) [@apo383](https://discourse.julialang.org/u/apo383)\
**Post date:** [January 15, 2024, 11:52pm UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/35 "2024-01-15T23:52:04Z")

</div>

Any particular reason for the name `discreterange`, as opposed to something like `integerrange`? I suppose “discrete” is meant to imply integers, in the sense that floats are (nearly) continuous. But discrete mathematics can refer to finite countable objects, not necessarily one-to-one with all integers (or Int64).

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 16, 2024, 12:33am UTC](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744/36 "2024-01-16T00:33:09Z")

</div>

> Any particular reason for the name `discreterange` , as opposed to something like `integerrange` ?

Not really, just the first name that came to mind when I needed such a function (:  
`uniqueintegerrange` would be the most descriptive, even though a bit on the longer side…

[Previous page](https://discourse.julialang.org/t/is-there-a-function-for-creating-n-nearly-evenly-spaced-integers-for-indexing/108744.md?page=1)
