Split vector in MATLAB

后端 未结 6 985
独厮守ぢ
独厮守ぢ 2020-12-15 07:06

I\'m trying to elegantly split a vector. For example,

vec = [1 2 3 4 5 6 7 8 9 10]

According to another vector of 0\'s and 1\'s of the same

6条回答
  •  时光说笑
    2020-12-15 07:34

    For this problem, a handy function is cumsum, which can create a cumulative sum of the cut array. The code that produces an output cell array is as follows:

    vec = [1 2 3 4 5 6 7 8 9 10];
    cut = [0 0 0 1 0 0 0 0 1 0];
    
    cutsum = cumsum(cut);
    cutsum(cut == 1) = NaN;  %Don't include the cut indices themselves
    sumvals = unique(cutsum);      % Find the values to use in indexing vec for the output
    sumvals(isnan(sumvals)) = [];  %Remove NaN values from sumvals
    output = {};
    for i=1:numel(sumvals)
        output{i} = vec(cutsum == sumvals(i)); %#ok
    end
    

    As another answer shows, you can use arrayfun to create a cell array with the results. To apply that here, you'd replace the for loop (and the initialization of output) with the following line:

    output = arrayfun(@(val) vec(cutsum == val), sumvals, 'UniformOutput', 0);
    

    That's nice because it doesn't end up growing the output cell array.

    The key feature of this routine is the variable cutsum, which ends up looking like this:

    cutsum =
         0     0     0   NaN     1     1     1     1   NaN     2
    

    Then all we need to do is use it to create indices to pull the data out of the original vec array. We loop from zero to max and pull matching values. Notice that this routine handles some situations that may arise. For instance, it handles 1 values at the very beginning and very end of the cut array, and it gracefully handles repeated ones in the cut array without creating empty arrays in the output. This is because of the use of unique to create the set of values to search for in cutsum, and the fact that we throw out the NaN values in the sumvals array.

    You could use -1 instead of NaN as the signal flag for the cut locations to not use, but I like NaN for readability. The -1 value would probably be more efficient, as all you'd have to do is truncate the first element from the sumvals array. It's just my preference to use NaN as a signal flag.

    The output of this is a cell array with the results:

    output{1} =
         1     2     3
    output{2} =
         5     6     7     8
    output{3} =
        10
    

    There are some odd conditions we need to handle. Consider the situation:

    vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14];
    cut = [1 0 0 1 1 0 0 0 0 1  0  0  0  1];
    

    There are repeated 1's in there, as well as a 1 at the beginning and end. This routine properly handles all this without any empty sets:

    output{1} = 
         2     3
    output{2} =
         6     7     8     9
    output{3} = 
        11    12    13
    

提交回复
热议问题