6

I have two vectors a and b as an example:

a = [1 2 3 4]; b = [5 6 7 8];

I want to create strings from the indices of a and b:

c1 = a(1):b(1) = [1 2 3 4 5];
c2 = a(2):b(2) = [2 3 4 5 6];
c3 = a(3):b(3) = [3 4 5 6 7];
c4 = a(4):b(4) = [4 5 6 7 8]; 

Then I want to concatenate the obtained strings:

C = cat(2, c1, c2, c3, c4) = [1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8];

I would like a general solution to help me automatize this algorithm.

Bowecho
  • 899
  • 2
  • 8
  • 17
  • Wouldn't `a(2):b(2) = [3 4 5 6]`? Also do you really want strings and not just vectors of doubles? – Dan Aug 21 '15 at 11:55
  • Yes, you're right, I made an edit. I changed something at first, and I forgot to update the result. – Bowecho Aug 21 '15 at 11:59

6 Answers6

5

Solution

This should do the trick without using a loop:

>> a = [1 3 4 5];
>> b = [5 6 7 8];
>> resultstr = num2str(cell2mat(arrayfun(@(x,y) x:y,a,b,'UniformOutput',false)))

resultstr =

1  2  3  4  5  3  4  5  6  4  5  6  7  5  6  7  8

Performance

I tried to do a quick comparison between this method, Luis Mendo's method and the for loop (see e.g. A. Visser's answer). I created two arrays with pseudo-random numbers from 1 to 50 and 501 to 1000 and timed the calculation for array sizes from 1 to 300, disregarding the string conversion.

Performance comparison

Luis Mendo's anwer is the clear winner, in terms of time complexity arrayfun seems to be on par with bsxfun. The for loop fares much worse, except for very small array sizes, but I'm not sure the timing can be trusted there.

The code can be found here. I'd be very happy to get some feedback, I'm a bit unsure about those measurements.

Community
  • 1
  • 1
dasdingonesin
  • 1,347
  • 1
  • 10
  • 16
  • Thanks, I was looking for such an approach. – Bowecho Aug 21 '15 at 12:05
  • Just so you know, `arrayfun` is actually a for-loop in disguise even though it fits on one line But nicely done anyway! – Benoit_11 Aug 21 '15 at 15:19
  • Benoit_11: The performance difference however is quite drastic, the `for` loop is ~20-30 times slower on my machine, probably because the resulting array can't be preallocated – I'm not a MATLAB performance expert though... – dasdingonesin Aug 21 '15 at 15:46
  • 1
    @dasdingonesin. Generally, it is better to use [`timeit`](http://uk.mathworks.com/help/matlab/ref/timeit.html) rather than `tic/toc` for accurate timing and benchmark. – Hoki Aug 21 '15 at 17:06
  • 1
    Thanks for the effort to do the timing! As Hoki says, `timeit` is more accurate for running time measurements – Luis Mendo Aug 21 '15 at 17:20
5

This can be done without loops (be they for, arrayfun or cellfun) using bsxfun's masking capability. This works also if the "strings" have different lengths, as in the following example.

a = [1 2 3];
b = [3 5 6];
m = (0:max(b-a)).'; %'
C = bsxfun(@plus, a, m);
mask = bsxfun(@le, m, b-a);
C = C(mask).';

The result in this example is:

C =
     1     2     3     2     3     4     5     3     4     5     6
Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

Try something like:

A = [1:5; 5:8];, C = [];
for i = A, C = [C i(1):i(2)]; end
Cstr = num2str(C);
Xxxo
  • 1,784
  • 1
  • 15
  • 24
1

I would do this:

a = [1 3 4 5]; b = [5 6 7 8];
c =[];
for i =1:length(a)
    c = [c [a(i):b(i)]];
end
num2str(c)
Tikoloche
  • 351
  • 1
  • 14
1

First of all, don't assign variables as C1, C2, C3 etc, use cells for that.

I'd use a for-loop for this, though there probably is a better alternative.

a = [1 3 4 5]; b = [5 6 7 8];
C = [];
for ii = 1:length(a)
    tmp = a(ii):b(ii);
    C = [C tmp];
end

This way tmp stores your separate arrays, then the following line adds it to the pre-existing array C.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
1

Just for fun:

a = [1 2 3 4]; b = [5 6 7 8];

A=fliplr(gallery('circul',fliplr([a,b])));
B=A(1:numel(a)+1,1:numel(a));
C=num2str(B(:).')
beaker
  • 16,331
  • 3
  • 32
  • 49