# The best way to define two or more arrays, similar to a given one

**URL:** https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519
**Category:** General Usage
**Created:** [July 12, 2021, 4:51pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519 "2021-07-12T16:51:38Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [July 12, 2021, 4:51pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/1 "2021-07-12T16:51:38Z")

</div>

Is there a method to avoid repeating `similar(u)` in the code below?  
To be more precise, I define a parameterized surface `(u,v)->(f(u,v), g(u,v), h(u,v))` with parameters in a rectangle `[a, b] x [c,d]`:

```julia
ru = a:0.1:b
rv = c:0.1:d
u, v = [ui for ui in ru, vi in rv], [vi for ui in ru, vi in rv]

x, y, z = similar(u), similar(u), similar(u)
@. x = f(u,v)
@. y = g(u,v)
@. z =h(u,v)

```

---

<div class="post-metadata">

### Author: ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)
#### Post date: [July 12, 2021, 4:59pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/2 "2021-07-12T16:59:02Z")

</div>

You can define something, if this happens enough:

```julia
julia> similars_v2(x...) = (similar(x...) for _ in 1:999);

julia> a,b,c = similars_v2([1,2], Float64);

julia> a[1] = 99;

julia> b
2-element Vector{Float64}:
 2.1863129326e-314
 2.2054957863e-314

```

Edit – initially I suggested this, which is a bad idea. Since `Iterators.repeated` is an ordinary function, its argument is evaluated once, and thus you get the same array repeatedly, not different arrays:

```julia
julia> similars(x...) = Iterators.repeated(similar(x...));

julia> a,b,c = similars([1,2], Float64);

julia> a[1] = 99;

julia> b
2-element Vector{Float64}:
 99.0
  2.175639858e-314

```

---

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [July 12, 2021, 7:35pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/3 "2021-07-12T19:35:18Z")

</div>

I’m coming back because I’ve noticed some strange behavior in IJulia.

If I paste these lines of code

```julia
u = [1, 2, 3.0, -4, 1, 0]
v = [5, 1, 0, 3, 7, 2.0]

x, y, z = similars(u)
@. x = u*u - v 
@. y = 2*u+u*v
@. z = v+u-u^2

```

in the same cell, and inspect x, y, z, they contain the same elements.

Initially (when I accepted this solution) I wrote in a cell:

```julia
@. x=...

```

and inspected its elements, then in another cell:

```julia
@. y=

```

etc and they had distinct elements. Why when the lines are written in the same cell x, y, z seem to have the same reference and as a consequence the same values?

---

<div class="post-metadata">

### Author: ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)
#### Post date: [July 12, 2021, 9:06pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/4 "2021-07-12T21:06:09Z")

</div>

You need no meshgrids or no `similar`s. You just need to do the following:

```julia
u = range(a, b; length=m+1)
v = range(c, d; length=n+1)

x = @. f(u, v')
y = @. g(u, v')
z = @. h(u, v')

```

Working example:

```julia
using Plots
pyplot()

function halftorus(n=25, a=5, b=10; lims=(-11, 11), size=(500, 400))
    u = range(-π/2, π/2, length=n+1)
    v = range(0, 2π, length=2n+1)
    x = @. (b + a * cos(u')) * cos(v)
    y = @. (b + a * cos(u')) * sin(v)
    z = @. a * sin(u') * one(v)
    surface(x, y, z; lims, colorbar=false, size)
end

halftorus()

```

![image](https://global.discourse-cdn.com/julialang/original/3X/4/6/468ea2d93bc9f70b272d4963590bbf2d052c7755.png)

---

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [July 12, 2021, 9:20pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/5 "2021-07-12T21:20:15Z")

</div>

Thank you @genkuroki,  
I know this definition, but I need the meshgrid, because I define a triangulation on the surface. First I construct the Delaunay triangulation on the points of the meshgrid, and then I lift it to the surface through the parameterization function.

---

<div class="post-metadata">

### Author: ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)
#### Post date: [July 12, 2021, 9:38pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/6 "2021-07-12T21:38:41Z")

</div>

Oh you are right, my answer is too quick. It calls `similar` once, not N times. Sorry! This is exactly like the `fill(ones(2), 3)` mistake.

---

<div class="post-metadata">

### Author: ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)
#### Post date: [July 12, 2021, 10:00pm UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/7 "2021-07-12T22:00:58Z")

</div>

If `u` and `v` are meshgrids, you can make `x`, `y`, and `z` with no `similar`s, more easily than above, by

```julia
x = @. f(u, v)
y = @. g(u, v)
z = @. h(u, v)

```

Note the positions of the `@.` macros.

---

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [July 13, 2021, 5:02am UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/8 "2021-07-13T05:02:37Z")

</div>

> [@empet](#):
>
> ```julia-auto
> u = [1, 2, 3.0, -4, 1, 0]
> v = [5, 1, 0, 3, 7, 2.0]
> 
> x, y, z = similars(u)
> @. x = u*u - v 
> @. y = 2*u+u*v
> @. z = v+u-u^2
> 
> ```

No, it doesn’t work. Commenting out:

```julia-auto
x, y, z =similars(u)

```

in the enclosed lines of code or in my original code with u, v as meshgrids, generates the error:

```julia-auto
UndefVarError: x not defined

```

Well, I’ll keep the less inspired setting:

```julia-auto
x, y, z = similar(u), similar(u), similar(u)

```

because it works. I asked this question just for finding out a more specialized method to allocate memory simultaneously, for x, y, z.

---

<div class="post-metadata">

### Author: ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)
#### Post date: [July 13, 2021, 5:42am UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/9 "2021-07-13T05:42:39Z")

</div>

Working example with no `similar`s:

```julia
using Plots
pyplot()

ru, rv = -1.5:0.1:1.5, -1:0.1:1
u, v = [ui for ui in ru, vi in rv], [vi for ui in ru, vi in rv]

x = @. u*u - v 
y = @. 2*u+u*v
z = @. v+u-u^2

surface(x, y, z; colorbar=false, size=(500, 400))

```

![image](https://global.discourse-cdn.com/julialang/original/3X/c/3/c31b6ace64afd5e4d0f16e7ee461c1369e433b50.png)

Please pay attention to the positions of `@.`s.

**Postscript:** (for further clarity)

For an `AbstractVector` `u`, the code `@. x = f(u)` is essentially equivalent to

```julia
for i in eachindex(u)
    x[i] = f(u[i])
end

```

If `x` is not defined in this code, then we get “UndefVarError: x not defined”.

But the code `x = @. f(u)` is essentially equivalent to

```julia
x = [f(u[i]) for i in eachindex(u)]

```

We obtain the new vector `x`.

If we just notice this difference, we can remove the redundant `similar`s.

Working example:

```julia
u = range(0, 1; length=7)
@. x = sinpi(u)

```

```julia
UndefVarError: x not defined
...

```

```julia
x = @. sinpi(u)

```

```julia
7-element Vector{Float64}:
 0.0
 0.5
 0.8660254037844386
 1.0
 0.8660254037844387
 0.4999999999999999
 0.0

```

---

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [July 13, 2021, 9:39am UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/11 "2021-07-13T09:39:11Z")

</div>

> [@genkuroki](#):
>
> ```julia
> using Plots
> pyplot()
> 
> ru, rv = -1.5:0.1:1.5, -1:0.1:1
> u, v = [ui for ui in ru, vi in rv], [vi for ui in ru, vi in rv]
> 
> x = @. u*u - v 
> y = @. 2*u+u*v
> z = @. v+u-u^2
> 
> surface(x, y, z; colorbar=false, size=(500, 400))
> 
> ```

Thank you so much for the solution and especially for explaning each definition!

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 15, 2021, 1:07am UTC](https://discourse.julialang.org/t/the-best-way-to-define-two-or-more-arrays-similar-to-a-given-one/64519/12 "2021-07-15T01:07:00Z")

</div>

> [@empet](#):
>
> Well, I’ll keep the less inspired setting:
> 
> ```julia-auto
> x, y, z = similar(u), similar(u), similar(u)
> 
> ```

Not that this is much more inspiring, but this is a possibility if that appears in another context:

```julia-auto
x, y, z = ntuple(i->similar(u),3)

```

and of course this could be made into a simple function like:

```julia-auto
similars(u,N) = ntuple(i->similar(u),N)

x, y, z = similars(u,3)

```
