Create matrix from two vectors

After defining a bivariate function f(x::Int, y::Int) , how can I get a matrix A = ( f(a[i], b[j]) ) using two vector a and b .

For example, let a = [1, 2] , b = [1, 2, 3] and f(x, y) = x + y , the desirble result should be

A = [2 3 4
     5 6 7]

Julia’s list comprehension seems to not work. Is there any simple way to realize it?

Hi!
I’m not sure which comprehension syntax you tried, but this one seems to work:

julia> f(x, y) = x + y
f (generic function with 1 method)

julia> a = [1, 2];

julia> b = [1, 2, 3];

julia> A = [f(a[i], b[j]) for i = 1:2, j = 1:3]
2×3 Matrix{Int64}:
 2  3  4
 3  4  5

Notice the subtle difference with that one:

julia> A = [f(a[i], b[j]) for i = 1:2 for j = 1:3]
6-element Vector{Int64}:
 2
 3
 4
 3
 4
 5
9 Likes

There’s also f.(a, b').

12 Likes

[m for m in Iterators.map(Base.splat(f), Iterators.product(a,b))]

Using StatsBase
pairwise(f,a,b)


That could possibly be written as broadcasting:

Base.splat(f).(Iterators.product(a,b))

Not directly related, but do you know why these two give different results?

julia> @btime broadcast(Base.splat(f), Iterators.product($a, $b))
  86.526 ns (2 allocations: 272 bytes)
3×2 Matrix{Int64}:
 2  3
 3  4
 4  5

julia> @btime map(Base.splat(f), Iterators.product($a, $b))
  46.457 ns (1 allocation: 112 bytes)
3×2 Matrix{Int64}:
 2  3
 3  4
 4  5
1 Like

I don’t know the answer. But, testing these two, to broadcast a function on an array of arrays, the speed difference leans towards broadcast:

f(x,y) = x + y
z = [rand(0:9,2) for _ in 1:1_000]
Base.splat(f).(z)       # 36.9 μs (1 allocation: 7.94 KiB)
map(Base.splat(f),z)    # 43.1 μs (1 allocation: 7.94 KiB)
1 Like