# Is there a clean one-liner to subset a vector of vectors?

**URL:** <https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249>\
**Category:** New to Julia\
**Tags:** question, indexing, arrays\
**Created:** [December 7, 2023, 2:31am UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249 "2023-12-07T02:31:49Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [December 7, 2023, 2:31am UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/1 "2023-12-07T02:31:50Z")

</div>

I have something like this:

```julia
julia> A = [[1,[2,3]], [4,[5,6]], [7,[8,9]]]
3-element Vector{Vector{Any}}:
 [1, [2, 3]]
 [4, [5, 6]]
 [7, [8, 9]]

julia> B = [A[i][2][1] for i in 1:length(A)]
3-element Vector{Int64}:
 2
 5
 8

julia> C = [A[i][2][2] for i in 1:length(A)]
3-element Vector{Int64}:
 3
 6
 9

```

Is there a cleaner way to extract B and C vectors out than a loop or just writing them out? Ie, my code looks like this:

```julia
B = [A[i][2][1] for i in 1:length(A)]
C = [A[i][2][2] for i in 1:length(A)]
D = ...

```

I really did read a bunch of questions on similar problems but didn’t manage to understand. I was about to put the comprehension in a function then loop over that, but then thought there has to be a way I am missing.

---

<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:** [December 7, 2023, 2:45am UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/2 "2023-12-07T02:45:25Z")

</div>

Do you have a meaningful name for what that second element represents? Or better yet, what its first/last components are? Use those names as functions:

```julia
frombulator(x) = x[2][1]
proznicator(x) = x[2][2]

```

Then your B and C are broadcasts:

```julia
B = frombulator.(A)
C = proznicator.(A)

```

Of course this works best if you have good meaningful names you can give these operations, and that’s often the hardest part of most programming.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 7, 2023, 12:46pm UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/3 "2023-12-07T12:46:04Z")

</div>

For this case you could try composing `first` and `last` then broadcasting.

```julia-repl
julia> B = (first ∘ last).(A)
3-element Vector{Int64}:
 2                                                                 
 5
 8                                                                
julia> C = (last ∘ last).(A)
3-element Vector{Int64}:                                           
 3
 6                                                                 
 9

```

To generalize we may need a helper.

```julia-repl
julia> nth(n) = x->x[n]
nth (generic function with 1 method)                              

julia> (nth(1) ∘ nth(2)).(A)                                      
3-element Vector{Int64}:
 2                                                                
 5
 8                                                                
julia> (nth(2) ∘ nth(2)).(A)                                      
3-element Vector{Int64}:
 3
 6                                                                
 9

```

Also rather than `1:length(A)` consider using `eachindex(A)`

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [December 7, 2023, 3:54pm UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/4 "2023-12-07T15:54:40Z")

</div>

Another option to add to the pile:

```julia
getij(i,j) = x -> getindex.(getindex.(x,i),j)
B = getij(2,1)(A)
C = getij(2,2)(A)

```

---

<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:** [December 7, 2023, 5:06pm UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/5 "2023-12-07T17:06:11Z")

</div>

A neat way to refer to nested parts of a data structure in general is to use optics. Here they fit perfectly:

```julia
julia> using AccessorsExtra

julia> getall(A, @o _[∗][2][1])
3-element Vector{Int64}:
 2
 5
 8

```

Can be more involved to grasp the concept at first, but becomes very convenient after that.

Btw, if you care about performance, it could be useful to rethink the data structure. Elements in your `A` array aren’t type stable, notice the `Any` in `3-element Vector{Vector{Any}}`.

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [December 7, 2023, 8:33pm UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/6 "2023-12-07T20:33:46Z")

</div>

Thanks all for the diversity of ideas, it has been very helpful.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [December 7, 2023, 8:34pm UTC](https://discourse.julialang.org/t/is-there-a-clean-one-liner-to-subset-a-vector-of-vectors/107249/7 "2023-12-07T20:34:30Z")

</div>

Another option that is usually one of the most readable/logical:

```julia
using TensorCast
@cast B[i] := A[i][2][1]
@cast C[i] := A[i][2][2]

```
