Search code examples
stringmatlabcell-array

How to extract substrings with different lengths?


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'

Solution

  • 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.