# Idiomatic way to write element-wise combination of array of arrays?

**URL:** <https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [December 8, 2018, 6:42pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467 "2018-12-08T18:42:01Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alec\_Loudenback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alec_loudenback/32/278_2.png) [@Alec\_Loudenback](https://discourse.julialang.org/u/Alec_Loudenback)\
**Post date:** [December 8, 2018, 6:42pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/1 "2018-12-08T18:42:01Z")

</div>

I was wondering how others would construct a combination of the product of two nested arrays?

Example and my approach:

```julia
a = [[1,2,3],[2,3,4]]  
b = [[1,1,1],[0,0,0]] 

# want [[1,2,3],[0,0,0]]

z = []
for (i,x) in enumerate(a)
    z = append!(z,[x .* b[i]])
end
z 

```

returns:

```julia
2-element Array{Any,1}:
 [1, 2, 3]
 [0, 0, 0]

```

I feel like my approach is a little clunky

---

<div class="post-metadata">

**Author:** ![davidbp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidbp/32/463_2.png) [@davidbp](https://discourse.julialang.org/u/davidbp)\
**Post date:** [December 8, 2018, 7:00pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/2 "2018-12-08T19:00:09Z")

</div>

Multiple dispatch is pretty cool:

```julia
 import Base.*

*(x::Array{Array{Int64,1},1}, y::Array{Array{Int64,1},1}) = [x_k .* y_k for (x_k,y_k) in zip(x,y)]

a = [[1,2,3],[2,3,4]]  
b = [[1,1,1],[0,0,0]] 

a*b
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [0, 0, 0]

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [December 8, 2018, 7:10pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/3 "2018-12-08T19:10:35Z")

</div>

How about

```julia
julia> broadcast.(*, a, b)
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [0, 0, 0]

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [December 8, 2018, 7:25pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/4 "2018-12-08T19:25:32Z")

</div>

This is also possible.

```julia
julia> ((x,y)->x.*y).(a,b)
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [0, 0, 0]

```

---

<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:** [December 8, 2018, 7:34pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/5 "2018-12-08T19:34:14Z")

</div>

Or define a broadcastable `*₊` function like this:

```julia
julia> *₊(a, b) = a .* b
*₊ (generic function with 1 method)

julia> a .*₊ b
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [0, 0, 0]

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [December 8, 2018, 8:24pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/6 "2018-12-08T20:24:18Z")

</div>

Note that my solution generalize well to arbitrary “depths”:

```julia
julia> aa = [a, a]
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 2, 3], [2, 3, 4]]
 [[1, 2, 3], [2, 3, 4]]

julia> ab = [a, b]
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 2, 3], [2, 3, 4]]
 [[1, 1, 1], [0, 0, 0]]

julia> broadcast.(broadcast, *, aa, ab)
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 4, 9], [4, 9, 16]]
 [[1, 2, 3], [0, 0, 0]]

```

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [December 8, 2018, 10:08pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/7 "2018-12-08T22:08:47Z")

</div>

Random thought:  
Could it be possible to define `(f.)` to be a function such that `(f.)(args...; kwargs...) = f.(args...; kwargs...)`? This way for nested broadcast one would do `(f.).(args...; kwargs...)`

I’m completely ignorant about the `broadcast` implementation and its subtleties, so this may be complete nonsense, but I became curious as the issue of multiplying nested arrays has been coming up occasionally.

---

<div class="post-metadata">

**Author:** ![yurivish](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yurivish/32/307_2.png) [@yurivish](https://discourse.julialang.org/u/yurivish)\
**Post date:** [December 8, 2018, 10:25pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/8 "2018-12-08T22:25:44Z")

</div>

> Random thought:  
> Could it be possible to define `(f.)` to be a function such that `(f.)(args...; kwargs...) = f.(args...; kwargs...)` ? This way for nested broadcast one would do `(f.).(args...; kwargs...)`

This came up recently on Slack and @StefanKarpinski thought it was a possibility.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [December 8, 2018, 11:00pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/9 "2018-12-08T23:00:37Z")

</div>

If you want a shorthand notation, maybe by abusing the exponentiation/power-like symbol…

```julia
julia> ↑¹(f, args) = broadcast(f, args...)
       ↑²(f, args) = ↑¹(broadcast, (f, args...))
       ↑³(f, args) = ↑²(broadcast, (f, args...));

julia> div↑¹([1], [2])
1-element Array{Int64,1}:
 0

julia> div↑²(b, a)
2-element Array{Array{Int64,1},1}:
 [1, 0, 0]
 [0, 0, 0]

julia> div↑³(ab, aa)
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 1, 1], [1, 1, 1]]
 [[1, 0, 0], [0, 0, 0]]

```

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 8, 2018, 11:23pm UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/10 "2018-12-08T23:23:03Z")

</div>

More generally, you can recursively define this broadcast up to any depth n like this

```nohighlight
julia> function rebroadcast(f,n,args...)
           n>1 ? rebroadcast(broadcast,n-1,(f,args...)) : broadcast(f, args...)
       end
rebroadcast (generic function with 1 method)

julia> rebroadcast(div,1,[1],[2])
1-element Array{Int64,1}:
 0

julia> rebroadcast(div,2,b,a)
2-element Array{Array{Int64,1},1}:
 [1, 0, 0]
 [0, 0, 0]

julia> rebroadcast(div,3,ab,aa)
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 1, 1], [1, 1, 1]]
 [[1, 0, 0], [0, 0, 0]]

```

---

<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:** [August 24, 2019, 12:54am UTC](https://discourse.julialang.org/t/idiomatic-way-to-write-element-wise-combination-of-array-of-arrays/18467/11 "2019-08-24T00:54:53Z")

</div>

> [@chakravala](#):
>
> rebroadcast(broadcast,n-1,(f,args…))

Sorry to bring this up now, but I think there are three more dots `...` missing there. This beautiful function should read:

```julia
julia> function rebroadcast(f,n,args...)
           n>1 ? rebroadcast(broadcast,n-1,(f,args...)...) : broadcast(f,args...)
       end
rebroadcast (generic function with 1 method)

julia> a = [[1,2,3],[2,3,4]]
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [2, 3, 4]

julia> b = [[1,1,1],[0,0,0]]
2-element Array{Array{Int64,1},1}:
 [1, 1, 1]
 [0, 0, 0]

julia> aa = [a, a]
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 2, 3], [2, 3, 4]]
 [[1, 2, 3], [2, 3, 4]]

julia> ab = [a, b]
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 2, 3], [2, 3, 4]]
 [[1, 1, 1], [0, 0, 0]]

julia> rebroadcast(div,1,[1],[2])
1-element Array{Int64,1}:
 0

julia> rebroadcast(div,2,b,a)
2-element Array{Array{Int64,1},1}:
 [1, 0, 0]
 [0, 0, 0]

julia> rebroadcast(div,3,ab,aa)
2-element Array{Array{Array{Int64,1},1},1}:
 [[1, 1, 1], [1, 1, 1]]
 [[1, 0, 0], [0, 0, 0]]

```
