# Iterate over a range in a non standard way

**URL:** <https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137>\
**Category:** General Usage\
**Tags:** sort, iterators\
**Created:** [October 10, 2024, 10:28am UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137 "2024-10-10T10:28:10Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![JM\_Beckers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jm_beckers/32/22482_2.png) [@JM\_Beckers](https://discourse.julialang.org/u/JM_Beckers)\
**Post date:** [October 10, 2024, 10:28am UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137/1 "2024-10-10T10:28:10Z")

</div>

I’m doing some exhaustive search loops and would like to cover say a range 10:100 but suspect (with quite some confidence) that the solution I look for is around 90. So I would like to loop over the range by starting at 90 and looking around to be possibly be able to break early: 90, 91,89,92,88,93,87,94,86,95,85,96,84,97,83,98,82,99,81,100,80, 79, … 10

I guess defining a custom iterator would be the best solution, but I’m not very familiar with it. Any suggestion what to be careful about if I launch myself into this?  
Thanks in advance

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [October 10, 2024, 10:50am UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137/2 "2024-10-10T10:50:48Z")

</div>

You can create a `struct` and implement the iteration interface for it:

> **[Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration)**
>
> Documentation for The Julia Language.

Alternatively, if you want a quick & simple solution, then something like this might work:

```julia
function myiterator(minval, maxval, guess)
    n = max(guess - minval, maxval - guess) + 1
    @assert n ≥ 0
    offset = [0; (repeat(1:n, inner=2) .* repeat([-1, 1], outer=n))];
    return filter(∈(minval:maxval), guess .- offset)
end

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 10, 2024, 11:15am UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137/3 "2024-10-10T11:15:33Z")

</div>

This seems to work without allocations

```julia
julia> struct RangeAround{R1,R2}
           lower::R1
           upper::R2
           function RangeAround(range::R, start) where R
               i = findfirst(==(start), range)
               i === nothing && error("Start point $start not in range $range")
               lower = reverse(range[begin:i])
               upper = range[i+1:end]
               new{typeof(lower), typeof(upper)}(lower, upper)
           end
       end

julia> Base.iterate(a::RangeAround) = (first(a.lower), 2)

julia> function Base.iterate(a::RangeAround, i)
           length_upper = length(a.upper)
           length_lower = length(a.lower)
           if i > length_upper + length_lower
               return nothing
           else
               shared_length = min(length_upper, length_lower)
               if i <= 2 * shared_length
                   return iseven(i) ? a.upper[i ÷ 2] : a.lower[(i + 1) ÷ 2], i + 1
               elseif length_upper > length_lower
                   return a.upper[i - shared_length], i + 1
               else
                   return a.lower[i - shared_length], i + 1
               end
           end
       end

```

```julia
julia> foreach(println, RangeAround(1:10, 8))
8
9
7
10
6
5
4
3
2
1

```

---

<div class="post-metadata">

**Author:** ![lbilli](https://avatars.discourse-cdn.com/v4/letter/l/59ef9b/32.png) [@lbilli](https://discourse.julialang.org/u/lbilli)\
**Post date:** [October 10, 2024, 12:13pm UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137/4 "2024-10-10T12:13:35Z")

</div>

You can try the one liner:

```julia
julia> collect(Iterators.flatten((Iterators.flatten(zip(90:-1:81, 91:100)), 80:-1:1)))
100-element Vector{Int64}:
 90
 91
 89
 92
 88
 93
 87
 94
  ⋮
  7
  6
  5
  4
  3
  2
  1

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 10, 2024, 12:45pm UTC](https://discourse.julialang.org/t/iterate-over-a-range-in-a-non-standard-way/121137/5 "2024-10-10T12:45:01Z")

</div>

> [@JM\_Beckers](#):
>
> I guess defining a custom iterator would be the best solution

Just writing explicit loops seems like it would be a lot easier than defining an iterator.

But even easier and more explicit would be to sort your range by how far the elements are from your target value of 90:

```julia
julia> sort(10:100, by=n->abs(n-90))
91-element Vector{Int64}:
 90
 89
 91
 88
 92
 87
 93
 86
  ⋮
 16
 15
 14
 13
 12
 11
 10

```
