# Broadcasting over combinations of inputs

**URL:** <https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785>\
**Category:** General Usage\
**Tags:** broadcast, math\
**Created:** [November 26, 2020, 12:21am UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785 "2020-11-26T00:21:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bmit/32/12443_2.png) [@bmit](https://discourse.julialang.org/u/bmit)\
**Post date:** [November 26, 2020, 12:21am UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/1 "2020-11-26T00:21:17Z")

</div>

I’m looking for a design pattern that will let me broadcast a function over two input lists, returning a 2D array of the output of the function for all possible pairs from the two lists.

In other words if my input arrays are:

```julia
x = [1, 2, 3]
y = ["a", "b"]

```

I’d like a succinct way to calculate

```julia
[ f(1, "a") f(2, "a") f(3, "a";
  f(1, "b") f(2, "b") f(3, "b") ]

```

for an arbitrary function `f()` of two inputs.

I’ve played with `Iterators.product` a little, but I’m not sure it does exactly what I’d like.

> julia\> (+).(collect(Iterators.product(1:4, [1, 2])))  
> ERROR: MethodError: no method matching +(::Tuple{Int64,Int64})

> julia\> (+).(collect(Iterators.product(1:4, [1, 2]))…)  
> (20, 12)

I should add that I’m looking for a performant way to do this for my application, so anything that makes additional copies of the data won’t work.

Are there any neat Julia tricks folks know of to do this without a `for` loop?

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [November 26, 2020, 1:09am UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/2 "2020-11-26T01:09:20Z")

</div>

Try

```julia
f.(permutedims(x), y)

```

or

```julia
[f(x,y) for y in y, x in x]

```

I think both should be pretty much optimal performance.

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [November 26, 2020, 6:41am UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/3 "2020-11-26T06:41:09Z")

</div>

I know you specifically asked about two inputs, but just as a general note, you can combine your idea of `Iterators.product` and @marius311’s use of comprehensions for any number of arguments:

```julia
[f(args...) for args in Iterators.product(x, y, z, a, b, c)]

```

would give you the 6-dimensional cube over all combinations of arguments.

---

<div class="post-metadata">

**Author:** ![bmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bmit/32/12443_2.png) [@bmit](https://discourse.julialang.org/u/bmit)\
**Post date:** [November 29, 2020, 5:06pm UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/4 "2020-11-29T17:06:18Z")

</div>

Thank you both! This is exactly what I was looking for.

---

<div class="post-metadata">

**Author:** ![bmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bmit/32/12443_2.png) [@bmit](https://discourse.julialang.org/u/bmit)\
**Post date:** [December 2, 2020, 11:48pm UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/5 "2020-12-02T23:48:04Z")

</div>

I’d like to point out to anyone referencing this that replacing

`f.(permutedims(x), y)`

with

`f.(x', y)`

does not work. It errors when `x` is a `Vector` of length one. It is trying to take the `Adjoint` (transpose) of the element itself in that case. I’m not sure if this is a bug or is intentional.

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [December 3, 2020, 9:06am UTC](https://discourse.julialang.org/t/broadcasting-over-combinations-of-inputs/50785/6 "2020-12-03T09:06:41Z")

</div>

Its intentional, `adjoint` is recursive like the mathematical construct, while `permutedims` is not (that was why I used the latter). I think [this](https://github.com/JuliaLang/julia/issues/20978) has some discussion of why, if I remember right. Fwiw, I don’t think vector length matters, e.g. `["a","b"]'` is also an error.
