Generate combinations of Cells that contain text

Hi there,
I am trying to generate all the combinations of certain cells so that each combination will include only one element of each vector/category. For example:
A = {'Square'; 'Rectangle'}
B = {'Heavy'; 'Light'; 'Medium'}
C = {'West'; 'East', 'South'; 'North'}
For output, I want a matrix that will have the following structure:
D = { 'Square-Heavy-West'; 'Square-Heavy-East' etc.}
If this would be possible without using cells, I would appreciate your thoughts.
Thank you in advance,
Andreas

5 Comments

You could give each word a number code and then have each row of the output simply be a series of numbers.
Appreciate your input but it is vital that the output includes text.
You can make a series of string variables, but I don't believe it is possible to make an array of strings without doing cells, structures, or a table. Since you're looking to mix and match a group of already existing strings cells seem to be your best choice.
Why are you trying to avoid cells?
I am open to using cells as well, just wondering if there is an alternative. But as I said, cells are fine too.
"...but I don't believe it is possible to make an array of strings without doing cells, structures, or a table"
String arrays were introduced in R2016b. These are by definition an array of strings.

Sign in to comment.

Answers (3)

Simple and efficient with ndgrid and strcat:
>> [Cx,Bx,Ax] = ndgrid(1:numel(C),1:numel(B),1:numel(A));
>> D = strcat(A(Ax(:)),'-',B(Bx(:)),'-',C(Cx(:)))
D =
'Square-Heavy-West'
'Square-Heavy-East'
'Square-Heavy-South'
'Square-Heavy-North'
'Square-Light-West'
'Square-Light-East'
'Square-Light-South'
'Square-Light-North'
'Square-Medium-West'
'Square-Medium-East'
'Square-Medium-South'
'Square-Medium-North'
'Rectangle-Heavy-West'
'Rectangle-Heavy-East'
'Rectangle-Heavy-South'
'Rectangle-Heavy-North'
'Rectangle-Light-West'
'Rectangle-Light-East'
'Rectangle-Light-South'
'Rectangle-Light-North'
'Rectangle-Medium-West'
'Rectangle-Medium-East'
'Rectangle-Medium-South'
'Rectangle-Medium-North'
"If this would be possible without using cells, I would appreciate your thoughts."
You could use string arrays, but the methods to generate all combinations would be exactly the same.

4 Comments

As a side note you can use ndgrid direclty on the cell arrays
[Cc, Bc, Aa] = ndgrid(C, B, A);
D = strcat(Aa(:), '-', Bb(:), '-', Cc(:))
As a side note you can use ndgrid direclty on the cell arrays
As I've discovered recently because one of my Answer didn't work for somebody on R2016a,
  • it's a fairly recent modification (of the full function on which ndgrid depends)
  • it's not documented, so use at your own peril.
It's very handy though, so this reminds me to raise a bug report to ask it to be documented (together with strfind working on numeric arrays).
RE: strfind, that is one of the examples where Octave sticks to the documented behavior, as it throws an error on numeric input. I know this question is not related to Octave, but I just wanted to put it out there.
I've always felt a bit ambivalent about the fact that strfind can find sequences in numeric arrays. It is very handy (and you'll find it suggested every now and then on Answers) but a function with such a name shouldn't deal with numbers.
The best thing would be to either change the name (FindSequence) or simply duplicate the function with a new name that clearly applies to numerics.

Sign in to comment.

This worked for me but I am not sure about how fast can it be compared with the loop, but still more elegant:
A = {'Square'; 'Rectangle'}; nA = size(A, 1);
B = {'Heavy'; 'Light'; 'Medium'}; nB = size(B, 1);
C = {'West'; 'East'; 'South'; 'North'}; nC = size(C, 1);
D = reshape(strcat(repmat(B, 1, nC), '-', repmat(C', nB, 1))', [], 1);
nD = size(D, 1);
D = reshape(strcat(repmat(A, 1, nD), '-', repmat(D', nA, 1))', [], 1);
If somebody knows a way to conduct this without loops feel free to mention it, but I do know that you can record all possible combinations using a set of for loops. Indexing can be a pain though if you just want a series of rows. Easier to look at as an output, just tricky to code.
lenA = size(A,1);
lenB = size(B,1);
lenC = size(C,1);
for first = 1:lenA; % Loop through first matrix
for second = 1:lenB; % Loop through second matrix
for third = 1:lenC; % Loop through third matrix
D{(first-1)*lenB*lenC+(second-1)*lenC+third,1} = A{first}; % Record word from first
D{(first-1)*lenB*lenC+(second-1)*lenC+third,2} = B{second}; % Record word from second
D{(first-1)*lenB*lenC+(second-1)*lenC+third,3} = C{third}; % Record word from third
% End single combination
end
end
end

Categories

Asked:

on 4 Apr 2018

Commented:

on 24 May 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!