# Generic array scan line

**URL:** <https://discourse.julialang.org/t/generic-array-scan-line/46816>\
**Category:** General Usage\
**Created:** [September 18, 2020, 1:17am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816 "2020-09-18T01:17:44Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [September 18, 2020, 1:17am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/1 "2020-09-18T01:17:44Z")

</div>

I have:

```julia
const w, h = 640, 480
a = rand(Float32, w, h)

```

and an algorithm, which requires scanning array `a` by row or column in all possible directions like shown here:

```julia
function scan4(a)
  scanLine = zeros(max(w, h))

  for i in 1:h
    foo!(scanLine, a[:, i])
  end

  scanLine = zeros(max(w, h))

  for i in h:-1:1
    foo!(scanLine, a[:, i])
  end

  scanLine = zeros(max(w, h))

  for i in 1:w
    foo!(scanLine, a[i, :])
  end

  scanLine = zeros(max(w, h))

  for i in w:-1:1
    foo!(scanLine, a[i, :])
  end
end

```

Is there a magic indexing trick, which would allow rewriting `scan4` function avoiding repetitions to get something like this without dramatic loss of performance:

```julia
function scan42(a)
  for indexingScheme in [colLeftRight, colRightLeft, rowTopDown, rowBottomUp]
    scanLine = zeros(max(w, h))

    for i in magicIndex(a, indexingScheme)
      foo!(scanLine, magicSlice(a, i, indexingScheme))
    end
  end
end

```

I’m looking for an existing API, which does something similar, not how to write something new from scratch using macros, unless it’s fairly simple and idiomatic to Julia.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [September 18, 2020, 2:12am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/2 "2020-09-18T02:12:47Z")

</div>

You can write generators like

```julia
col_left_right = ( view(a, :, i) for i in 1:size(a, 2) )
```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 18, 2020, 4:19am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/3 "2020-09-18T04:19:38Z")

</div>

> [@dpsanders](#):
>
> ```julia
> col_left_right = ( view(a, :, i) for i in 1:size(a, 2) )
> 
> ```

Isn’t it [`eachcol`](https://docs.julialang.org/en/v1/base/arrays/#Base.eachcol)?

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [September 18, 2020, 4:22am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/4 "2020-09-18T04:22:21Z")

</div>

> [@tkf](#):
>
> Isn’t it [`eachcol`](https://docs.julialang.org/en/v1/base/arrays/#Base.eachcol)?

It is for `colLeftRight` scan, but can I get `eachcol` in reverse for `colRightLeft` scan?

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 18, 2020, 4:24am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/5 "2020-09-18T04:24:30Z")

</div>

It looks like you can do `Iterators.reverse(eachcol(xs))` (but not `reverse(eachcol(xs))`).

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [September 18, 2020, 4:28am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/6 "2020-09-18T04:28:40Z")

</div>

This is another option, but I don’t know if it’s efficient:

```julia
eachcol(reverse(a, dims=2))

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 18, 2020, 4:31am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/7 "2020-09-18T04:31:06Z")

</div>

`reverse` copies an array. It’s not efficient if you have a gigantic array.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 18, 2020, 6:28am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/8 "2020-09-18T06:28:49Z")

</div>

> [@tkf](#):
>
> Iterators.reverse(eachcol(xs))

Should be `Iterators.reverse.(eachcol(xs))` from my understanding.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 18, 2020, 6:31am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/9 "2020-09-18T06:31:48Z")

</div>

> [@tomerarnon](#):
>
> Should be `Iterators.reverse.(eachcol(xs))`

In that case, `(Iterators.reverse(c) for c in eachcol(xs))` for a non-allocating version. `Iterators.map(Iterators.reverse, eachcol(xs))` would also work in Julia 1.6.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 18, 2020, 7:12am UTC](https://discourse.julialang.org/t/generic-array-scan-line/46816/10 "2020-09-18T07:12:57Z")

</div>

> [@pauljurczak](#):
>
> I’m looking for an existing API, which does something similar, not how to write something new from scratch using macros, unless it’s fairly simple and idiomatic to Julia.

Read this part only after writing the below. My bad 😅

* * *

Technically, you can do

```julia
function scan4(a)
    w, h = size(a)
    magic_iterator = (eachcol,
                      xs -> (@view(c[end:-1:1]) for c in eachcol(xs)),
                      eachrow,
                      xs -> (@view(c[end:-1:1]) for c in eachrow(xs)))

    for f in magic_iterator
        scanLine = zeros(max(w, h))
        for x in f(a)
            foo!(scanLine, x)
        end
    end
end

```

but this is not type stable (the type of `f` changes each iteration) so not that good of an idea. You can generate the 4 loops with:

```julia
@generated function scan4_gen(a)
    magic_iterator = (eachcol,
                      xs -> (@view(c[end:-1:1]) for c in eachcol(xs)),
                      eachrow,
                      xs -> (@view(c[end:-1:1]) for c in eachrow(xs)))

    expr = quote w, h = size(a) end

    for i in 1:length(magic_iterator)
        iter = quote
            scanLine = zeros(max(w, h))
            for x in $(magic_iterator[i])(a)
                foo!(scanLine, x)
            end
        end
        push!(expr.args, iter)
    end

    expr
end

```

which “saves typing” and is fast, but at great expense to readability… If you wanted to generalize to scanning N-D arrays, a generated function is what I would suggest. For this though 🤷‍♂️ ymmv. I can’t think of another way that doesn’t also incur its own costs.

I went with `@view(c[end:-1:1]` since `Iterators.reverse` doesn’t support iteration (maybe not necessary though). Note that in 1.5+, you should use `@view(c[end:-1:begin])`.
