# Creating an array of tuples (why doesn't filter work on a zip?)

**URL:** <https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173>\
**Category:** General Usage\
**Created:** [August 29, 2019, 4:24pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173 "2019-08-29T16:24:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [August 29, 2019, 4:24pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/1 "2019-08-29T16:24:05Z")

</div>

I’m pretty sure the answer is that a zip type, is not an Array, BitArray or AbstractArray and that’s what my problem is.

I also read the definition for zip and it “runs multiple iterators”, also resultant type is not an array, so that takes care of why filter doesn’t work on a zipped thing directly.

which of course would make my question: how do i create an array of tuples from two arrays ?

then the obvious came to me

```julia
[(x,y) for (x,y) in zip(a,b)]

```

and I’m thinking, Shirley there’s a better way… I picked a bad week to give up nootropics.

```julia
julia> a=collect(1:5)
b5-element Array{Int64,1}:=
 1
 2
 3
 4
 5

julia> b=randn(5)
5-element Array{Float64,1}:
  1.622863416635525 
 -0.2613170739500653
 -0.2399681094935552
 -0.9209180059024933
 -0.9645905168069914

julia> xy=zip(a,b)
Base.Iterators.Zip{Tuple{Array{Int64,1},Array{Float64,1}}}(([1, 2, 3, 4, 5], [1.62286, -0.261317, -0.239968, -0.920918, -0.964591]))

julia> filter((x,y)->x>5, xy)
ERROR: MethodError: no method matching filter(::getfield(Main, Symbol("##5#6")), ::Base.Iterators.Zip{Tuple{Array{Int64,1},Array{Float64,1}}})
Closest candidates are:
  filter(::Any, ::Array{T,1} where T) at array.jl:2351
  filter(::Any, ::BitArray) at bitarray.jl:1710
  filter(::Any, ::AbstractArray) at array.jl:2312
  ...
Stacktrace:
 [1] top-level scope at none:0

```

---

<div class="post-metadata">

**Author:** ![DrPapa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drpapa/32/6835_2.png) [@DrPapa](https://discourse.julialang.org/u/DrPapa)\
**Post date:** [August 29, 2019, 4:44pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/2 "2019-08-29T16:44:58Z")

</div>

I cannot answer your question about why `filter` doesn’t have a method for iterators, but a few simpler alternatives to your list comprehension are

```julia
[x for x in zip(a,b)]

```

and

```julia
collect(zip(a,b))

```

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [August 29, 2019, 4:50pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/3 "2019-08-29T16:50:38Z")

</div>

> [@DrPapa](#):
>
> collect(zip(a,b))

that’s much better 🙂

it turns out that my original error was due to trying to operate on a zip AND because you can’t use (x,…) in an anonymous function ☹

```julia
julia> filter((x,y)->x >4, xy)
ERROR: MethodError: no method matching (::getfield(Main, Symbol("##3#4")))(::Tuple{Int64,Float64})
Closest candidates are:
  #3(::Any, ::Any) at REPL[3]:1
Stacktrace:
 [1] mapfilter(::getfield(Main, Symbol("##3#4")), ::typeof(push!), ::Array{Tuple{Int64,Float64},1}, ::Array{Tuple{Int64,Float64},1}) at .\abstractset.jl:340
 [2] filter(::Function, ::Array{Tuple{Int64,Float64},1}) at .\array.jl:2351
 [3] top-level scope at none:0

julia> filter(x->x[1] >4, xy)
6-element Array{Tuple{Int64,Float64},1}:
 (5, -1.4070836855785198) 
 (6, -1.1832075841742866) 
 (7, -1.7970550232653926) 
 (8, -1.0736587226498235) 
 (9, -0.42599362336170415)
 (10, -1.7261573057529163)

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 29, 2019, 5:15pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/4 "2019-08-29T17:15:33Z")

</div>

There are a couple of things going on. Firstly, it appears that filter doesn’t support `Zip` iterators. That’s a bit surprising, maybe? You’ll have to collect the `Zip` object into a vector of tuples.

Secondly, iterating over a collection of tuples gives you a tuple at a time, and you cannot destructure them like that.

So,

```julia
xy = zip(1:5, rand(5)) # don't collect the range
filter(x->x[1]>3, collect(xy)) # x is a tuple
# or you can do this
filter(((x, y),)->x>3, collect(xy)) # notice the extra parens

```

You could also use a comprehension:

```julia
[tup for tup in xy if tup[1]>3] # this works with the `Zip` object

```

---

<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:** [August 29, 2019, 5:20pm UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/5 "2019-08-29T17:20:40Z")

</div>

> [@DNF](#):
>
> Firstly, it appears that filter doesn’t support `Zip` iterators. That’s a bit surprising, maybe?

If you want to filter an iterator to produce another iterator (not an array), you can use `Iterators.filter`, e.g.

```julia
Iterators.filter(((x,y),) -> x > 0, zip(a,b))

```

You can `collect` the result to get an array, but you can also loop over it (e.g. `for (x,y) in Iterators.filter(...)`) without actually allocating the filtered collection.

---

<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:** [August 30, 2019, 6:49am UTC](https://discourse.julialang.org/t/creating-an-array-of-tuples-why-doesnt-filter-work-on-a-zip/28173/6 "2019-08-30T06:49:59Z")

</div>

Just for completeness, there is `((x, y) for (x, y) in zip(a, b) if x > 0)` whose filtering part is lowered to an `Iterators.filter` object. Repeating `(x, y)` twice is somewhat ugly though.
