【问题标题】:vectorized array creation from a list of start/end indices从开始/结束索引列表创建矢量化数组
【发布时间】:2011-02-17 22:24:45
【问题描述】:

我有一个两列矩阵M,其中包含一组间隔的开始/结束索引:

startInd   EndInd
1          3
6          10
12         12
15         16

如何生成所有区间索引的向量:

v = [1 2 3 6 7 8 9 10 12 15 16];

我正在使用循环执行上述操作,但我想知道是否有更优雅的矢量化解决方案?

v = [];
for i=1:size(M,1)
    v = [v M(i,1):M(i,2)];
end

【问题讨论】:

    标签: matlab vectorization


    【解决方案1】:

    这是我喜欢用于这个特定问题的矢量化解决方案,使用函数cumsum

    v = zeros(1, max(endInd)+1);  % An array of zeroes
    v(startInd) = 1;              % Place 1 at the starts of the intervals
    v(endInd+1) = v(endInd+1)-1;  % Add -1 one index after the ends of the intervals
    v = find(cumsum(v));          % Perform a cumulative sum and find the nonzero entries
    

    【讨论】:

    • 是的,我知道有一个简单的解决方案。十分优雅。 +1
    • 正是我想要的......谢谢
    • 请注意,如果 idxs 可以很大,OPs 解决方案实际上会更快,例如,idxs = [1 3; 6 11; 12 12; 25000 26000] 在我的机器上。
    【解决方案2】:
    cell2mat(arrayfun(@colon,M(:,1)',M(:,2)','UniformOutput',false))
    

    我没有 IMFILL,但在我的机器上,这种方法比其他建议更快,而且我认为由于使用了 find 会击败 IMFILL 方法。

    如果将 M 设置为转置(我们调整 arrayfun 的第三个和第四个参数),它可以变得更快。

    【讨论】:

    • 对于idxs = [1 3;等输入6 11; 12 12; 25000 26000],这个解决方案比 gnovice 的要快,但是 OP 的简单 for 循环仍然快得多。对于 OP 的示例输入,这比 gnovice 慢,也比 OP 的 for 循环慢。
    【解决方案3】:

    非常奇怪的解决方案恕我直言,创建临时字符串并使用 EVAL。也可以是单线。

    tmp = cellstr(strcat(num2str(M(:,1)),{':'},num2str(M(:,2)),{' '}));
    v = eval(['[' cell2mat(tmp') ']']);
    

    我知道它可能不适用于大型矩阵。只是为了好玩。

    【讨论】:

      【解决方案4】:

      可能有一个更好的解决方案,我不知何故没有看到,但这里有一个使用 IMFILL 的版本

      startInd = [1,6,12,15];
      endInd = [3,10,12,16];
      
      %# create a logical vector with starts and ends set to true to prepare for imfill
      tf = false(endInd(end),1);
      tf([startInd,endInd]) = true;
      
      %# fill at startInd+1 wherever startInd is not equal endInd
      tf = imfill(tf,startInd(startInd~=endInd)'+1); %' SO formatting
      
      %# use find to get the indices
      v = find(tf)'  %' SO formatting
      
      v =
           1     2     3     6     7     8     9    10    12    15    16
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-02
        • 2021-04-03
        • 2020-01-07
        • 2020-06-15
        • 1970-01-01
        • 2017-06-18
        • 1970-01-01
        相关资源
        最近更新 更多