# Filter! vs filter

**URL:** <https://discourse.julialang.org/t/filter-vs-filter/42414>\
**Category:** New to Julia\
**Created:** [July 2, 2020, 7:38am UTC](https://discourse.julialang.org/t/filter-vs-filter/42414 "2020-07-02T07:38:28Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fleimgruber](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fleimgruber/32/16127_2.png) [@fleimgruber](https://discourse.julialang.org/u/fleimgruber)\
**Post date:** [July 2, 2020, 7:38am UTC](https://discourse.julialang.org/t/filter-vs-filter/42414/1 "2020-07-02T07:38:28Z")

</div>

Why is the mutating version of filter failing in this example?

```julia
limit = 10
marked = 2
candidates = marked:limit
multiples = [marked * i for i in 2:fld(limit, marked)]
filter(x -> x in multiples, candidates)

```

gives

```julia
4-element Array{Int64,1}:
  4
  6
  8
 10

```

but

```julia
filter!(x -> x in multiples, candidates)

```

gives

```julia
setindex! not defined for UnitRange{Int64}

Stacktrace:
 [1] error(::String, ::Type) at ./error.jl:42
 [2] error_if_canonical_setindex(::IndexLinear, ::UnitRange{Int64}, ::Int64) at ./abstractarray.jl:1082
 [3] setindex! at ./abstractarray.jl:1073 [inlined]
 [4] filter!(::var"#25#26", ::UnitRange{Int64}) at ./array.jl:2390
 [5] top-level scope at In[24]:1

```

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [July 2, 2020, 7:47am UTC](https://discourse.julialang.org/t/filter-vs-filter/42414/2 "2020-07-02T07:47:30Z")

</div>

The error is telling you why: `setindex!` is not defined for `UnitRange` objects, that is you can’t change a single element in a `UnitRange`

The reason for this is that `UnitRange` is an efficient iterator, that doesn’t actually store all of the elements in the range, but just the starting point, end point, and step size. If you want to alter individual elements of your range, you should `collect()` your range into a vector.

---

<div class="post-metadata">

**Author:** ![fleimgruber](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fleimgruber/32/16127_2.png) [@fleimgruber](https://discourse.julialang.org/u/fleimgruber)\
**Post date:** [July 2, 2020, 4:12pm UTC](https://discourse.julialang.org/t/filter-vs-filter/42414/3 "2020-07-02T16:12:43Z")

</div>

Thanks for spelling this out and the fix!

I wrongly assumed that the a:b shorthand ends up being the same type as the corresponding array. The visual difference of the representation in the output of the shorthand definition vs. an array should have been another clue that those are really two different types.

---

<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:** [July 2, 2020, 4:21pm UTC](https://discourse.julialang.org/t/filter-vs-filter/42414/4 "2020-07-02T16:21:03Z")

</div>

Keep in mind that you really only need to `collect` ranges like `1:n` when you need to modify them, otherwise it’s better to just use them _as is_, since they behave just like vectors. Too many new users `collect` them needlessly.

---

<div class="post-metadata">

**Author:** ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)\
**Post date:** [July 3, 2020, 12:12am UTC](https://discourse.julialang.org/t/filter-vs-filter/42414/5 "2020-07-03T00:12:50Z")

</div>

You can still use `candidates` to refer to the new filtered data without loosing any performance using Julia’s powerful `Iterators`. In this case, you don’t have to materialize and allocate new memory.

```julia
julia> limit = 10;
julia> marked = 2;
julia> candidates = marked:limit;
julia> multiples = [marked * i for i in 2:fld(limit, marked)];

julia> candidates = Iterators.Filter(in(multiples), candidates)
Base.Iterators.Filter{Base.Fix2{typeof(in),Array{Int64,1}},UnitRange{Int64}}(Base.Fix2{typeof(in),Array{Int64,1}}(in, [4, 6, 8, 10]), 2:10)

julia> println.(candidates);
4
6
8
10

julia> println.(2 .* candidates);
8
12
16
20

```
