# Trying to reference a struct field into an array

**URL:** <https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366>\
**Category:** New to Julia\
**Tags:** arrays, struct\
**Created:** [August 25, 2022, 10:03pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366 "2022-08-25T22:03:17Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![moataz-sabry](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moataz-sabry/32/36856_2.png) [@moataz-sabry](https://discourse.julialang.org/u/moataz-sabry)\
**Post date:** [August 25, 2022, 10:03pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/1 "2022-08-25T22:03:17Z")

</div>

I’m trying to create a vector `as`, that contains the value of field `a` for each struct `Foo` in the vector of structs `foo` without losing reference so that changing the values of `as` would also affect the values of `foo`. Here is a simple example:

```julia
julia> mutable struct Foo{N<:Number}
           a::N
           b::N
       end

julia> foo = [Foo(1, 1), Foo(2, 2)]
2-element Vector{Foo{Int64}}:
 Foo{Int64}(1, 1)
 Foo{Int64}(2, 2)

julia> as = [f.a for f in foo]
2-element Vector{Int64}:
 1
 2

julia> as[1] = 3
3

julia> foo[1]
Foo{Int64}(1, 1) ## my target here is to have Foo{Int64}(3, 1) as result instead

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 25, 2022, 10:20pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/2 "2022-08-25T22:20:55Z")

</div>

well, since numbers are immutable, when you have `f.a`, you lost reference to struct because values are just values.

either you keep `foo` around and do `foo[1].a = 3`, or you have to put `Ref`s inside the struct `Foo` instead of plain numbers

---

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [August 25, 2022, 10:40pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/3 "2022-08-25T22:40:06Z")

</div>

@jling is right — doing exactly what you ask for is impossible so long as the struct fields are immutable. But what you ask for is the default behavior for mutable fields (such as arrays or a number in a `Ref`), in which case the struct itself need not be mutable.

I just wanted to add, maybe you will find [`StructArrays.jl`](https://juliaarrays.github.io/StructArrays.jl/stable/) useful. It lets you deal with arrays-of-structs, while internally being a struct-of-arrays. Used in conjunction with [`Accessors.jl`](https://github.com/JuliaObjects/Accessors.jl), this can be pretty handy. See [this answer](https://discourse.julialang.org/t/does-this-style-of-property-broadcasting-already-exist/85288/4).

---

<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:** [August 26, 2022, 5:32am UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/4 "2022-08-26T05:32:51Z")

</div>

For this specific usecase, you only need StructArrays. And the `Foo` struct doesn’t even have to be mutable.

```julia
julia> foo = [Foo(1, 1), Foo(2, 2)] |> StructArray
2-element StructArray(::Vector{Int64}, ::Vector{Int64}) with eltype Foo{Int64}:
 Foo{Int64}(1, 1)
 Foo{Int64}(2, 2)

julia> as = foo.a
2-element Vector{Int64}:
 1
 2

julia> as[1] = 3
3

julia> foo[1]
Foo{Int64}(3, 1)

```

---

<div class="post-metadata">

**Author:** ![moataz-sabry](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moataz-sabry/32/36856_2.png) [@moataz-sabry](https://discourse.julialang.org/u/moataz-sabry)\
**Post date:** [August 26, 2022, 3:19pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/5 "2022-08-26T15:19:30Z")

</div>

thanks a lot for suggesting `StructArrays`. Any ideas how to customise `StructArray` in case of nested structs?, something like following:

```julia
using StructArrays

julia> struct SubFoo{N<:Number}
           x::N
           y::N
           z::N
       end

julia> struct Foo{N<:Number}
          a::SubFoo{N}
          b::N
       end

julia> foo = [Foo(SubFoo(1, 2, 3), 1), Foo(SubFoo(1, 2, 3), 2)] |> StructArray
2-element StructArray(::Vector{SubFoo{Int64}}, ::Vector{Int64}) with eltype Foo{Int64}:
 Foo{Int64}(SubFoo{Int64}(1, 2, 3), 1)
 Foo{Int64}(SubFoo{Int64}(1, 2, 3), 2)

julia> foo.a.x ## not possible, would be nice to get [1, 1] as a result

```

---

<div class="post-metadata">

**Author:** ![stepanzh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stepanzh/32/34851_2.png) [@stepanzh](https://discourse.julialang.org/u/stepanzh)\
**Post date:** [August 26, 2022, 7:14pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/6 "2022-08-26T19:14:55Z")

</div>

Storing `Foo.a` as `StructVector{SubFoo...}`?..

---

<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:** [August 26, 2022, 7:59pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/7 "2022-08-26T19:59:44Z")

</div>

This part of StructArrays is less known, but works fine:

```julia
julia> foo = StructArray([Foo(SubFoo(1, 2, 3), 1), Foo(SubFoo(1, 2, 3), 2)]; unwrap=T -> fieldcount(T) > 0)
2-element StructArray(StructArray(::Vector{Int64}, ::Vector{Int64}, ::Vector{Int64}), ::Vector{Int64}) with eltype Foo{Int64}:
 Foo{Int64}(SubFoo{Int64}(1, 2, 3), 1)
 Foo{Int64}(SubFoo{Int64}(1, 2, 3), 2)

julia> foo.a.x
2-element Vector{Int64}:
 1
 1

```

And just in case you need something even fancier:

```julia
julia> using AccessorsExtra, SplitApplyCombine

julia> ax = mapview(@optic(_.a.x + 10), foo)
2-element <...>:
 11
 11

julia> ax[1] = 0
0

julia> foo
2-element <...>:
 Foo{Int64}(SubFoo{Int64}(-10, 2, 3), 1)
 Foo{Int64}(SubFoo{Int64}(1, 2, 3), 2)

```

Works with all arrays including Base Vectors.

---

<div class="post-metadata">

**Author:** ![moataz-sabry](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moataz-sabry/32/36856_2.png) [@moataz-sabry](https://discourse.julialang.org/u/moataz-sabry)\
**Post date:** [August 26, 2022, 9:25pm UTC](https://discourse.julialang.org/t/trying-to-reference-a-struct-field-into-an-array/86366/8 "2022-08-26T21:25:11Z")

</div>

thanks, the first solution works perfectly for me. I’ve just gone with `T <: SubFoo` instead of `fieldcount(T) > 0`, as `fieldcount` wouldn’t work with `abstract types` or `Unions`.
