0

I have an n by 2 matrix that contains start and end indices of substrings of a specified string. How can I extract the n by 1 cell array of substrings without a for-loop?

string = 'Hello World!';
ranges = [1 1;
    2 3;
    4 5;
    3 7];
substrings = cell(size(ranges, 1), 1);
for i=1:size(ranges, 1)
    substrings{i} = string(ranges(i, 1):ranges(i, 2));
end

The expected result:

substrings = 
'H'
'el'
'lo'
'llo W'
saastn
  • 5,717
  • 8
  • 47
  • 78
  • See [here](https://stackoverflow.com/questions/38501128/efficient-colon-operator-for-multiple-start-and-end-points) and [here](https://stackoverflow.com/questions/39429966/create-an-index-vector-based-on-start-and-stop-values) two related questions. – rahnema1 Nov 08 '20 at 01:22

1 Answers1

2

You can use cellfun to make it a single-line operation:

str = 'Hello World!';
ranges = [  1 1;
            2 3;
            4 5;
            3 7];
% first convert "ranges" to a cell object
Cranges = mat2cell(ranges,ones(size(ranges,1),1),2);
% call "cellfun" on every row/entry of "Cranges"
cellfun(@(x)str(x(1):x(2)),Cranges, 'UniformOutput',false)

ans =

4×1 cell array

{'H'    }
{'el'   }
{'lo'   }
{'llo W'}

I have changed the variable string to str because string is a native function in MATLAB (converting the input to the type string).

Although this is single-line operation, it doesn't mean that it is more efficient:

Num = 1000000;
        
substrings = cell(size(ranges, 1), 1);
% time for-loop
tic
for j = 1:Num
    for i = 1:size(ranges, 1)
        substrings{i} = str(ranges(i, 1):ranges(i, 2));
    end
end
toc;

Cranges = mat2cell(ranges,ones(size(ranges,1),1),2);
% time function-call
tic
for j = 1:Num
    substrings = cellfun(@(x)str(x(1):x(2)),Cranges, 'UniformOutput',false);
end
toc;
Elapsed time is 3.929622 seconds. 
Elapsed time is 50.319609 seconds.
max
  • 3,915
  • 2
  • 9
  • 25