How to vertical concatenate cell with strings

2 views (last 30 days)
Ray
Ray on 24 Feb 2017
Commented: Guillaume on 25 Feb 2017
Hi,
I have a bunch of cells with strings like this:
S1(2,3)={'Hello'};
S1(1,2)={'SomeString'}
S2(2,3)={'World'};
S2(3,3)={'AnotherString'}
And I want to apply strvcat on each cell to get a matrix like this:
S3 =
[] 'SomeString' []
[] [] [2x5 char]
[] [] 'AnotherString'
where S3{2,3}
ans =
Hello
World
Is there a fast way to get this without using a loop?
  2 Comments
Jan
Jan on 24 Feb 2017
Do you really want to get a char Matrix as output? This is a rather unpractical format for storing multiple strings.
Ray
Ray on 24 Feb 2017
The type of output is not that important for me. As long as I can combine my matrices and preserve the indices. If my suggested cell containing chars is unpractical I'm open for any good soloution. What would be a better approach, though?

Sign in to comment.

Answers (2)

Guillaume
Guillaume on 24 Feb 2017
Edited: Guillaume on 25 Feb 2017
Using the new string class introduced in R2016b, this is trivial to do (as long as the empty elements in the cell arrays are actually empty strings and not empty matrices)
S1(cellfun(@isempty, S1)) = {''}; %replace empty matrices by empty char arrays
S2(cellfun(@isempty, S2)) = {''};
string(S1) + string(S2)
Pre-R2016b, you indeed have to use a loop, easily coded as:
cellfun(@strcat, S1, S2, 'UniformOutput', false)
  2 Comments
Ray
Ray on 25 Feb 2017
Edited: Ray on 25 Feb 2017
Almost... (You missed a bracket)
S1(cellfun(@isempty, S1)) = {''} %replace empty matrices by empty char arrays S2(cellfun(@isempty, S2)) = {''}
substituting strcat with strvcat and looping as you suggested does what I want.
cellfun(@strvcat, S1, S2, 'UniformOutput', false)
But I can't get it using the string class. Btw is it possible to preallocate a cell with empty chars? This would at least avoid one loop.
Guillaume
Guillaume on 25 Feb 2017
Sorry about the typo.
I missed that you wanted to vertically concatenate the strings. I'm sure your example originally showed
HelloWorld
not
Hello
World
The way to create a multiline string with the string class is by putting a '\n' character between each line. This would be achieved with compose. Due to the way compose works, you would have to do some reshaping before and after, so I'm not sure it's going to be any faster:
reshape(compose('%s\n%s', string(S1(:)), string(S2(:))), size(S1))
Preallocating a cell array with empty chars can be done with
c = repmat({''}, sz) %where sz is the desired size
But if you're going to use the string class, you can directly create the empty array
s = strings(sz)
Note: if you're not happy with the way multiline strings work with string, then your only choice is indeed multi-row char array in a cell array with cellfun. However, be aware that multirow char arrays are a kind of weird beast. Most string manipulation functions only work with single row char array and those that don't error may not behave properly. e.g:
fprintf('This look weird: %s\n', ['Hello';'World'])
Furthermore since char array are matrices all rows must have the same number of elements, hence shorter rows must be padded with spaces ( strvcat does that for you), wasting memory.

Sign in to comment.


Ray
Ray on 25 Feb 2017
Edited: Ray on 25 Feb 2017
Ok, I'm guessing there is no way to strvcat using string class, or am I missing something? So I need to stick to the loop and preallocating?
S1 = cell(3, 3);
S1(:) = {''}
S2 = cell(3, 3);
S2(:) = {''}
S1(2,3)={'Hello'};
S1(1,2)={'SomeString'}
S2(2,3)={'World'};
S2(3,3)={'AnotherString'}
cellfun(@strvcat, S1, S2, 'UniformOutput', false)
As I do have a whole a lot of 512x512 matrices this is really slow as each cellfun needs ~3 sec on my computer :(

Categories

Find more on Characters and Strings in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!