# Enumeratezip

I often would like to use something like `enumerate(a,b,c)` and get the functionality:

``````a,b,c = rand(10),rand(10),rand(10)
for (i,ai,bi,ci) in enumerate(a,b,c)
@show i ai bi ci
end
``````

something that could emulate this is `enumeratezip(a...) = zip(eachindex(first(a)), a...)` so that

``````a,b,c = rand(10),rand(10),rand(10)
for (i,ai,bi,ci) in enumeratezip(a,b,c)
@show i ai bi ci
end
``````

I don’t know if this can be problematic in some cases and maybe there’s a more elegant version to do the same thing without defining `enumeratezip` or writing the `zip` by hand. I would be interested to know! Maybe this feature is something that someone else came across wanting to have?

``````julia> for (i,(ai,bi,ci)) in enumerate(zip(a,b,c))
@show i ai bi ci
end
i = 1
ai = 0.9570998904436379
bi = 0.5775517184568557
ci = 0.3987638983159012
i = 2
ai = 0.9761040253755489
bi = 0.7214272853124479
ci = 0.7986223352162409
i = 3
ai = 0.9435897685169268
bi = 0.10027768357097111
ci = 0.41432976381125064
i = 4
...
``````

?

6 Likes

Looks like a decent idea to me, but you could run into a couple issues with just using `eachindex(a)` if `a`, `b`, and `c` aren’t the same…:

1. …shape: you could want to index into `b` and `c` with `i`, but `eachindex(a)` could return indices that only work for `a`. Simple to fix, just compute indices from `eachindex(b)` and `eachindex(c)` too.
2. …size: if `b` or `c` is smaller than `a`, the loop will terminate before you exhaust `eachindex(a)`. This isn’t necessarily a problem, but someone not looking too closely could think `a` was exhausted at the last iteration because that’s what you chose to `eachindex`. A comment or adding those indices from `b` and `c` would help make it clearer, I think.

It’s not bad! But still I find it a little unnecessarily clumsy.

Really? I really like the elegance of composition, instead of having to make a custom function.

2 Likes

oh no of course that’s much better! I guess I just would like to have `enumerate` to support splatting

You can already use `zip(rand(10),rand(11))`, so something similar must be possible enumerating the whole thing?

Note that that `enumerate` does always start at 1, while `eachindex` might not. For example:

``````julia> using OffsetArrays: OffsetVector

julia> v = OffsetVector(['a', 'b', 'c'], 5)
3-element OffsetArray(::Vector{Char}, 6:8) with eltype Char with indices 6:8:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

julia> enumerate(v) |> collect
3-element Vector{Tuple{Int64, Char}}:
(1, 'a')
(2, 'b')
(3, 'c')

julia> zip(eachindex(v), v) |> collect
3-element OffsetArray(::Vector{Tuple{Int64, Char}}, 6:8) with eltype Tuple{Int64, Char} with indices 6:8:
(6, 'a')
(7, 'b')
(8, 'c')

``````

Not really sure if there is a proper `enumerate` equivalent for multiple iterables. `enumerate( zip (a, b, c) )` wouldn’t work because whatever index you get is intended for the `zip` object, not `a,b,c`.
`zip(eachindex(a), eachindex(b), a, b)` would be closer, but there must be a more elegant way to do that given `d = (a, b, c)`, similar to your `enumeratezip(a...)` call.

My intention was actually not meant for the case of an `OffsetArray`. I guess the solution by @DNF is what I will go with. And after looking at it a bit longer I might get used to the double brackets, separating index and elements!