# Keep array elements that are NOT in a list of indexes

**URL:** <https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555>\
**Category:** General Usage\
**Tags:** indexing, arrays\
**Created:** [February 4, 2025, 8:51pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555 "2025-02-04T20:51:20Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![JM\_Beckers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jm_beckers/32/22482_2.png) [@JM\_Beckers](https://discourse.julialang.org/u/JM_Beckers)\
**Post date:** [February 4, 2025, 8:51pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/1 "2025-02-04T20:51:20Z")

</div>

Suppose I have a list of indexes `mylist`, is there an equivalent of

```julia
setdiff(myarray, myarray[mylist])

```

but using directly the fact that I know which elements are to the eliminated (through `mylist`) in order to be more efficient?

Edit: I can indeed assume mylist is sorted so that deleteat! can be used.

---

<div class="post-metadata">

**Author:** ![cocoa1231](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cocoa1231/32/22215_2.png) [@cocoa1231](https://discourse.julialang.org/u/cocoa1231)\
**Post date:** [February 4, 2025, 8:55pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/2 "2025-02-04T20:55:24Z")

</div>

You can use

```julia
filter(!in(myarray[mylist])), myarray)

```

---

<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:** [February 4, 2025, 9:29pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/3 "2025-02-04T21:29:49Z")

</div>

> [@cocoa1231](#):
>
> `filter(!in(myarray[mylist])), myarray)`

That deletes elements of `myarray` whose _values_ match those in `myarray[mylist]`, which might include elements at other indices.

If you only want to filter by the _indices_ (not values), I would use something like:

```julia
 myarray[filter(!in(mylist), eachindex(myarray))]

```

or

```julia
 myarray[filter(!in(Set(mylist)), eachindex(myarray))]

```

if `mylist` is big enough that it’s worth converting to a `Set`.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [February 4, 2025, 9:34pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/4 "2025-02-04T21:34:21Z")

</div>

You can also use InvertedIndices.jl. I think it should be one of the more efficient methods these days.

```Julia
using InvertedIndices: Not
myarray[Not(mylist)]

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [February 4, 2025, 9:39pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/5 "2025-02-04T21:39:43Z")

</div>

> [@stevengj](#):
>
> ` myarray[filter(!in(Set(mylist)), eachindex(myarray))]`

I would be careful here — if that `mylist` is a bunch of integers and you happen to have an array that unexpectedly uses Cartesian indices, this will silently _not skip anything_.

You probably want to be explicit and ask for `LinearIndices` or `CartesianIndices` rather than `eachindex` (unless of course your `mylist` set is built using stuff out of `eachindex`).

---

<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:** [February 4, 2025, 11:41pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/6 "2025-02-04T23:41:09Z")

</div>

Often `mylist` would be sorted, and then the algorithm can be a merge-like and faster. For example:

```julia
list = collect(1:10)
mylist = [2,3,5,7]

function slash(mylist, list)
    foldl(eachindex(list); init=(sizehint!(eltype(list)[], length(list)-length(mylist)), 1)) do (res,j),i
    if j > length(mylist) || i != mylist[j]
        push!(res, list[i])
        return (res, j)
    else
        return (res, j+1)
    end
    end |> first
end

@btime slash($mylist, $list)
# 29.972 ns (2 allocations: 128 bytes)

function slash2(mylist, list)
    list[filter(!in(Set(mylist)), eachindex(list))]
end

@btime slash2($mylist, $list)
# 135.140 ns (10 allocations: 688 bytes)

```

The example shows `slash` which assumes presorting is 4x faster than `slash2`.

(BTW `slash` is needlessly using `foldl`, a simple `for` would be easier)

Ideally, a `mylist` of indices which are sorted could be storred in a SortedVector type which would automatically dispatch to a faster method.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 4, 2025, 11:56pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/7 "2025-02-04T23:56:44Z")

</div>

> [@mbauman](#):
>
> You can also use [InvertedIndices.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/InvertedIndices). I think it should be one of the more efficient methods these days.

InvertedIndices is better than it was before, but still tends to be several times slower than `deleteat!(copy(A), I)` (just Base, no dependencies) or `@delete A[I]` (Accessors).

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [February 5, 2025, 8:45am UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/8 "2025-02-05T08:45:57Z")

</div>

```julia
julia> using InvertedIndices: Not

julia> using BenchmarkTools

julia> v=rand(1:1000,100) 
100-element Vector{Int64}:
 549
 342
 738
   8
 616
 697
   ⋮
  94
 986
 764

julia> ei=[3,7,13,26,44,57,65,87,98]
9-element Vector{Int64}:
  3
  7
 13
 26
 44
 57
 65
 87
 98

julia> function slicesort(v,ei)
           d=Vector{Int}(undef,length(v)-length(ei))
           doff=1
           soff=1
          for i in ei
               N=i-soff
               unsafe_copyto!(d,doff,v,soff,N)
               soff=i+1
               doff+=N
           end
           copyto!(d,doff,v,soff,length(v)-soff+1)
          d
       end
slicesort (generic function with 1 method)

julia> @btime [v[i] for i in eachindex($v) if i ∉ $ei];
  3.000 μs (57 allocations: 2.80 KiB)

julia> @btime v[Not(ei)];
  259.941 ns (2 allocations: 832 bytes)

julia> @btime deleteat!(copy(v), ei);
  111.693 ns (1 allocation: 896 bytes)

julia> @btime slicesort(v,ei);
  96.093 ns (1 allocation: 816 bytes)

julia> v[Not(ei)]==deleteat!(copy(v),ei)==slicesort(v,ei)
true

```

---

<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:** [February 5, 2025, 12:40pm UTC](https://discourse.julialang.org/t/keep-array-elements-that-are-not-in-a-list-of-indexes/125555/9 "2025-02-05T12:40:55Z")

</div>

> [@rocco\_sprmnt21](#):
>
> ```julia
> julia> @btime [v[i] for i in eachindex($v) if i ∉ $ei];
> 3.000 μs (57 allocations: 2.80 KiB)
> 
> ```

`v[i]` should be `$v[i]`, otherwise you are benchmarking with type-unstable globals. (This makes it 8x faster on my machine, though still slower than the other methods.)

(In general, interpolate `$v` and `$ei` in your other benchmarks too, but not doing it in the explicit loop hurts the most.)
