# Test whether an iterable is strictly increasing

**URL:** <https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 13, 2023, 1:53pm UTC](https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282 "2023-06-13T13:53:40Z")\
**Posts on this page:** 4\
**Page:** 1

<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:** [June 13, 2023, 1:53pm UTC](https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282/1 "2023-06-13T13:53:40Z")

</div>

Is there a simple way to test if an iterable (not necessarily instantiated) is _strictly_ increasing? (Cf [this long topic on why `issorted(itr, lt = <)` does not do this](https://discourse.julialang.org/t/understanding-issorteds-lt-keyword/60918/)). The solution has to be non-allocating.

Simplest I could come up with is a generalization of `issorted` to

```julia
"Test if `f(this, next)` holds for all consecutive elements of `itr`. If not, return early."
function is_pairwise(f, itr)
    y = iterate(itr)
    y === nothing && return true
    prev, state = y
    y = iterate(itr, state)
    while y !== nothing
        this, state = y
        f(prev, this) || return false
        prev = this
        y = iterate(itr, state)
    end
    return true
end

is_pairwise(<, [0.1, 0.1]) # false

```

`IterTools.partition` allows a simple implementation too.

---

<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:** [June 13, 2023, 2:02pm UTC](https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282/2 "2023-06-13T14:02:40Z")

</div>

`Iterators.peel` makes this a bit simpler (you can avoid the low-level `iterate` call), while avoiding the allocations of `IterTools.partition`:

```julia
function is_pairwise(f, itr)
    p = Iterators.peel(itr)
    isnothing(p) && return true
    prev, rest = p
    for cur in rest
        f(prev, cur) || return false
        prev = cur
    end
    return true
end

```

---

<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:** [June 13, 2023, 5:30pm UTC](https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282/3 "2023-06-13T17:30:21Z")

</div>

where exactly does the allocation with the use of partition happen?

```julia
all(Base.splat(<).(IterTools.partition(itr1,2,1)))

```

```julia
julia> @btime IterTools.partition($itr,2,1)
  1.500 ns (0 allocations: 0 bytes)
IterTools.Partition{UnitRange{Int64}, 2}(1:10, 1)

```

```julia
julia> itr=[i^2 for i in 1:10]
10-element Vector{Int64}:
   1
   4
   9
  16
  25
  36
  49
  64
  81
 100

julia> itr1=rand(1:10,10)
10-element Vector{Int64}:
  8
 10
  9
  2
  5
  6
 10
  7
  3
 10
julia> using IterTools

julia> @btime all(Base.splat(<).(IterTools.partition(itr1,2,1)))
  2.389 μs (44 allocations: 2.44 KiB)
false

julia> @btime all(Base.splat(<), IterTools.partition($itr1,2,1))
  320.290 ns (9 allocations: 528 bytes)
false

julia> @btime all(Base.splat(<), IterTools.partition($itr,2,1))
  1.360 μs (37 allocations: 2.05 KiB)
true

```

---

<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:** [June 14, 2023, 1:56pm UTC](https://discourse.julialang.org/t/test-whether-an-iterable-is-strictly-increasing/100282/4 "2023-06-14T13:56:46Z")

</div>

> [@rocco\_sprmnt21](#):
>
> where exactly does the allocation with the use of partition happen?

For a general iterator it returns arrays (which need to be allocated):

```julia
julia> collect(Iterators.partition((i for i in 1:5), 2))
3-element Vector{Vector{Any}}:
 [1, 2]
 [3, 4]
 [5]

```
