# Equivalent of \`last\` for iterators

**URL:** <https://discourse.julialang.org/t/equivalent-of-last-for-iterators/95874>\
**Category:** General Usage\
**Tags:** iterators\
**Created:** [March 10, 2023, 4:41pm UTC](https://discourse.julialang.org/t/equivalent-of-last-for-iterators/95874 "2023-03-10T16:41:50Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 10, 2023, 4:41pm UTC](https://discourse.julialang.org/t/equivalent-of-last-for-iterators/95874/1 "2023-03-10T16:41:51Z")

</div>

While responding to a different topic, I needed the last element of an iterator. This has at least one fairly simple and efficient solution which has appeared elsewhere:

```julia
itrlast(itr) = foldl((_,y)->y,itr)

```

but `last` can also return several elements from the end of a collection, so here is a suggested function to achieve this generally:

```julia
using CircularArrays
using IterTools

function itrlast(itr, n::Integer)
    n > 0 || error("Must keep at least one element")
    pi = peekiter(itr)
    e = peek(pi)
    isnothing(e) && "Iterator is empty"
    T = eltype(something(e))
    buf, i = foldl(((buf,i),e)->(buf[i+1] = e; (buf,i+1)),pi;
      init=(CircularArray(Vector{T}(undef,n)),0))
    i<n && error("Iterator has less than $n elements")
    @view buf[i-n+1:i]
end

```

With this method defined, the following works:

```julia
julia> itrlast(1:10,2)
2-element view(CircularVector(::Vector{Int64}), 9:10) with eltype Int64:
  9
 10

```

and also:

```julia
julia> itrlast(Iterators.take(iterated(x->√(6+x),1.0),23),5)
5-element view(CircularVector(::Vector{Float64}), 19:23) with eltype Float64:
 2.9999999999999787
 2.9999999999999964
 2.9999999999999996
 3.0
 3.0

```

This function, and perhaps `last` as well, can be generalized to “index” any iterator with an index range (e.g. 1:3:10 or ?? last(1:3:end, 5) of an itr ??).

Comments, ideas welcome.

---

<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:** [March 10, 2023, 5:13pm UTC](https://discourse.julialang.org/t/equivalent-of-last-for-iterators/95874/2 "2023-03-10T17:13:05Z")

</div>

> [@Dan](#):
>
> While responding to a different topic, I needed the last element of an iterator. This has at least one fairly simple and efficient solution which has appeared elsewhere:

The most efficient thing is to `first(Iterators.reverse(itr))`. This works for any iterator that supports the [reverse iteration](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) interface (many but not all iterators). There was a PR to make this the default behavior for `last` ([julia#42991](https://github.com/JuliaLang/julia/pull/42991)), but it was reverted as being too breaking.

Of course, many iterators that support reverse iteration [also implement `last`](https://github.com/JuliaLang/julia/commit/3049893a8b58c3e3ee1a44203793be5442cf88e5).

If there is any iterator that does not support reverse iteration but _could_ (efficiently), a pull request is generally welcome. There are some open issue that are waiting for someone to tackle them, e.g. [julia#39079](https://github.com/JuliaLang/julia/issues/39079) and [julia#43740](https://github.com/JuliaLang/julia/issues/43740).

> [@Dan](#):
>
> so here is a suggested function to achieve this generally

This is fine, but the reason that `last` doesn’t do this kind of thing in general is that it is documented as being O(1).
