# Compose Yourself! 5

Posted by **Loren Shure**,

Even if we crunch numbers a lot, there are plenty of times, for example, when reporting, that we need to mix numbers into text. For a very long time, we've been able to create a character vector, and more recently, a `string`, with functions like `sprintf`. Look here for more information on character arrays and strings.

That's fine if we want to create one textual entity, but what if I need an array of them? I can use `sprintf` in a loop, or I can use a newer function, `compose`. Let me show you a bit how they each work.

### Contents

#### A Single Numeric Input

Let's create some numeric values to use as possible inputs.

nums = [exp(1) pi]

nums = 2.7183 3.1416

Here's character output from `sprintf`:

```
cs1 = sprintf('%d', nums(2))
```

cs1 = '3.141593e+00'

And here's the equivalent `string` output:

```
ss1 = sprintf("%d", nums(2))
```

ss1 = "3.141593e+00"

Now let's try `compose`:

```
cc1 = compose('%d', nums(2))
```

cc1 = 1×1 cell array {'3.141593e+00'}

sc1 = compose("%d", nums(2)) % What do we have in our workspace? whos

sc1 = "3.141593e+00" Name Size Bytes Class Attributes ans 1x4 8 char cc1 1x1 136 cell ccm1 1x2 272 cell cs1 1x12 24 char csm1 1x26 52 char nums 1x2 16 double sc1 1x1 174 string scm1 1x2 252 string ss1 1x1 174 string ssm1 1x1 206 string tc 1x1 120 cell tmpc 1x2 228 cell tmps 1x2 4 char ts 1x2 4 char

What you may notice is that both `sprintf` and `compose` give the same output for the string version. However, for the character output, we get one character array using `sprintf`, but that same array embedded in a cell using `compose`.

clearvars -except nums

#### Multiple Numeric Inputs

Now let's see what happens if we are formatting output with more than a single numeric input.

csm1 = sprintf('%d ',nums) ssm1 = sprintf("%d ",nums) ccm1 = compose('%d',nums) scm1 = compose("%d",nums)

csm1 = '2.718282e+00 3.141593e+00 ' ssm1 = "2.718282e+00 3.141593e+00 " ccm1 = 1×2 cell array {'2.718282e+00'} {'3.141593e+00'} scm1 = 1×2 string array "2.718282e+00" "3.141593e+00"

whos

Name Size Bytes Class Attributes ccm1 1x2 272 cell csm1 1x26 52 char nums 1x2 16 double scm1 1x2 252 string ssm1 1x1 206 string

What we see is that we get exactly the same types of output as before. But for the `string` version with `compose`, we get output matching the dimensions of the input, in this case, `1x2`, whereas with the `sprintf` version, we get a single array for all of the cases. `sprintf` always produces a single array as output and recycles the hole (the formatter) while there is more data to format. `compose` returns arrays of text.

#### Handling Holes

Again, `sprintf` produces one output, regardless of the dimensions of the input.

tmps = sprintf('%d',[1 2]) tmpc = compose('%d',[1 2])

tmps = '12' tmpc = 1×2 cell array {'1'} {'2'}

Also, `sprintf` truncates a hole if you don’t provide data. `compose` leaves it there in case you want to fill it with a subsequent call:

ts = sprintf('\n %s') tc = compose('\n %s')

ts = ' ' tc = 1×1 cell array {'↵ %s'}

#### Your Turn

Do you need to format text/numbers? What techniques do you use to get the results you want? Let us know here.

Get the MATLAB code

Published with MATLAB® R2019a

**Category:**- Strings

## 5 CommentsOldest to Newest

**1**of 5

**2**of 5

>> a = 1:4; >> [{} arrayfun(@(x)sprintf('Example %d',x), a, 'uniformoutput', false)] ans = 1×4 cell array {'Example 1'} {'Example 2'} {'Example 3'} {'Example 4'}Indeed 10 years ago I made a function to create sets of labels discrete spaces over several sets of axes strprod (string product) that worked on cellstr arrays

>> strprod({'amps ' 'volts '}, {'motor1' 'motor2'}, {' mean' ' min' ' max'}) 2×2×3 cell array ans(:,:,1) = {'amps motor1 mean' } {'amps motor2 mean' } {'volts motor1 mean'} {'volts motor2 mean'} ans(:,:,2) = {'amps motor1 min' } {'amps motor2 min' } {'volts motor1 min'} {'volts motor2 min'} ans(:,:,3) = {'amps motor1 max' } {'amps motor2 max' } {'volts motor1 max'} {'volts motor2 max'}Nowadays I can use a string expression to create the same space

>> ["amps " "volts "]' + ["motor"+(1:2)+" "] + permute(["mean" "min" "max"], [3 1 2]) 2×2×3 string array ans(:,:,1) = "amps motor1 mean" "amps motor2 mean" "volts motor1 mean" "volts motor2 mean" ans(:,:,2) = "amps motor1 min" "amps motor2 min" "volts motor1 min" "volts motor2 min" ans(:,:,3) = "amps motor1 max" "amps motor2 max" "volts motor1 max" "volts motor2 max" >>

**3**of 5

**4**of 5

**5**of 5

title("the value is "+number)@Julian- So nice to hear that this saves you a lot of code and some hassle! Thanks for the illustration. @Rob- Please put in an enhancement request via tech support for your thoughts on the tick labels for the colorbar. In the meantime, at least you have a relatively simple way to accomplish your goal. Thanks! @Stuart- Sure you can use string (not strings):

>> nums = 1:5 nums = 1 2 3 4 5 >> string(nums) ans = 1×5 string array "1" "2" "3" "4" "5"

## Recent Comments