how to convert a cell to string in matlab

user1804229 picture user1804229 · Nov 6, 2012 · Viewed 82.6k times · Source

Suppose I have a cell

v =    'v'    [576.5818]    [3.0286]    [576.9270]

       'v'    [576.5953]    [3.1180]    [576.8716]

       'f'    [      56]    [    58]    [      52]

       'f'    [      56]    [    58]    [      52]

and I want to convert this to a cell array using a format string for each element:' %.5f'

How can I do this? I tried the following approach, but I get an error:

f1 = @(x) sprintf('   %.5f',x);
cellfun(f1, num2cell(v),'UniformOutput', false) 

I am getting an error as ???

Error using ==> sprintf

Function is not defined for 'cell' inputs.

Error in ==> @(x)sprintf(' %.5f',x)

Can any one help me thanks in advance

Answer

Yauhen Yakimovich picture Yauhen Yakimovich · Mar 18, 2013

String is a cell array

Well, not really.. It is a matrix, but continue reading.

I guess cell array is the most mystic data type in MATLAB. So let's demystify it a bit ;-)

Assume

fruits = {...
    'banana',...
    'apple',...
    'orange'...
}

First of all integer indexing is not needed for small arrays. It is much better to use foreach-like constructions. Indeed,

for index = 1:numel(fruits)
    fruits{index}
end

is equivalent to

for fruit = fruits
    fruit
end

right?

Well, not quite. First loop produces strings, while the second one gives cells. You can check it with

for index = 1:numel(fruits)
    [isstr(fruits{index}) iscell(fruits{index})]
end

for fruit = fruits
    [isstr(fruit) iscell(fruit)]
end

, i.e. [1 0] and [0 1].

If you have spot the difference, then you must know what to do with the next example (in this one is really relate to your question (!) I promise!). Say you try to do horizontal concatenation in a loop:

for fruit = fruits
    [fruit 'is a fruit']
end

You will get

ans = 

    'banana'    'is a fruit'

and so on. Why? Apparently this code tries to concatenate a nested cell array to a string (a cell array containing a matrix of chars which constitute the string like 'banana'). So, correct answer is

Use {:}

for fruit = fruits
    [fruit{:} 'is a fruit']
end

Magically this already produces the expected 'banana is a fruit', 'apple is a fruit', etc.

Hints

A few hints:

  • Index-free looping works nicely with structs as in for fruit = [fieldnames][1](fruits)'
  • The above is true for open source octave
  • banana is not just fruit, taxonomically it is also a herb ;-) just like 'banana' in MATLAB is both a string and a matrix, i.e. assert(isstr('banana') && ismat('banana')) passes, but assert(iscell('banana')) fails.
  • {:} is equivalent to cell2mat

PS

a solution to your question may look like this:

Given

vcell = {...
    'v'    576.5818    3.0286  576.9270;
    'v'    576.5818    3.0286  576.9270    
}

covert index-wise only numeric types to strings

 vcell(cellfun(@isnumeric, vcell)) =  cellfun(@(x) sprintf('%.5f', x), vcell(cellfun(@isnumeric, vcell)), 'UniformOutput', false)

Above code outputs

vcell =

'v'    '576.58180'    '3.02860'    '576.92700'
'v'    '576.58180'    '3.02860'    '576.92700'

which can be concatenated.