user2971693
user2971693

Reputation: 75

How to apply a binary function in Matlab on two vectors to get a matrix of all pairwise results?

Is there any function in Matlab that can take two vectors (not necessarily of the same size) and apply a binary function on every pair of the vector's elements resulting in a matrix n1xn2, where n1 and n2 are the lengths of the input vectors?

Something similar to pdist2, but with arbitrary function pointer instead of the distance function.

Example usage:
v1 = [1, 2, 3]
v2 = [2, 3]

Apply(@plus, v1, v2) -> [3, 4; 4, 5; 5, 6];

Note: although, the example is numerical, the actual vectors I need to work with are arrays of cells each containing a string (all strings have equal length). The binary function takes two strings and returns a scalar, for example - strcmp.

Upvotes: 2

Views: 502

Answers (3)

chappjc
chappjc

Reputation: 30579

An answer to the OP's last comment (very different from the content of the question) would be the following:

>> v1 = [{'one'}, {'two'}]; v2 = [{'two'}, {'three'}];
>> cellfun(@strcmp,repmat(v1',1,size(v2,2)),repmat(v2,size(v1,2),1))

ans =

     0     0
     1     0

For the example numeric data and the plus operation in the question, that is solved by:

>> v1 = [1, 2, 3]; v2 = [2, 3];
>> bsxfun(@plus,v1',v2)

ans =

     3     4
     4     5
     5     6

However, I think the answer to the string concatenation problem is answered well by Luis Mendo.

In general, to do an operation for all pairs, bsxfun should be your go-to function for numeric arrays. For cells, strings, and other non-POD types, consider combinations of repmat, arrayfun and cellfun. It's hard to be more specific without a more specific question.

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112659

You can achieve that with ndgrid and arrayfun. Consider the following example data (cell arrays of strings):

v1 = {'aa','bb','cc'};
v2 = {'1','22'};

and example function (string concatenation):

fun = @(str1, str2) [str1 str2]

Then:

M = length(v1);
N = length(v2);
[ii jj] = ndgrid(1:M, 1:N);
reshape(arrayfun(@(k) fun(v1{ii(k)},v2{jj(k)}) , 1:M*N, 'uni', false), M,N)

gives the desired result:

ans = 

    'aa1'    'aa22'
    'bb1'    'bb22'
    'cc1'    'cc22'

In the general case, simply define v1, v2 and fun as needed.

Upvotes: 1

Stewie Griffin
Stewie Griffin

Reputation: 14939

This one works on the example data:

repmat(v2,numel(v1),1)+[v1(:), v1(:)]

ans =
     3     4
     4     5
     5     6

Update

Try something like this if numel(v2) ~= 2 (still only for the numerical example you have provided):

repmat(v2,numel(v1),1)+repmat(v1(:),1,numel(v2))

Upvotes: 0

Related Questions