【问题标题】:Fill cell array with elements based on the indices MATLAB使用基于索引 MATLAB 的元素填充元胞数组
【发布时间】:2015-01-31 19:55:59
【问题描述】:

我有一个 n*m 元胞数组 Cell_In:

a b
* *
* *
c *
* d
* *
* f

* --> 表示空字符串 ('')。这是我需要的:

a b
a b
a b
c b
c d
c d
c f

对于特定列,我需要用前一个非空单元格填充空单元格,直到找到另一个非空单元格。以下是我写的代码。

b = ~cellfun(@isempty,a);
c = [find(b(:,1) == 1);size(a,1)+1]; e = diff(c);
d = [find(b(:,2) == 1);size(a,1)+1]; f = diff(d);
s1 = ''; s2 = '';
for i = 1:length(e)
    s1 = [s1,repmat(a(c(i),1),1,e(i))];
end

for i = 1:length(f)
    s2 = [s2,repmat(a(d(i),2),1,f(i))];
end
Cell_Out = [s1',s2'];

它工作正常,但我想知道最好的解决方案?

【问题讨论】:

    标签: matlab cell-array


    【解决方案1】:

    假设A 是输入元胞数组,这里可能有两种方法。

    方法#1

    %// Initlialize output array
    Aout = cell(size(A));
    
    for k = 1:size(A,2)
    
        %// Select one column
        Ak = A(:,k);
    
        %// Logical array with size of Ak and ones at places with non-empty strings
        pos = cellfun(@(x) ~isempty(x), Ak);
    
        %// Find unique strings and find indices for all places in that column
        %// with respect to those unique strings
        [unq_str,~,str_idx] = unique(Ak,'stable');
    
        %// Perform cumsum on pos to get an array with a "stepped" array that
        %// steps up at each non-empty string position.
        %// Then replace each stepping number with the string IDs
        idx = changem(cumsum(pos),str_idx(pos),1:sum(pos));
    
        %// Index into each column with those replaced IDs for the final output
        Aout(:,k) = unq_str(idx);
    end
    

    为了更积极地测试解决方案代码而稍微更改了输入,我们在代码运行之后 -

    A = 
        'a'    'b'
        ''     '' 
        ''     'a'
        'c'    '' 
        ''     'd'
        'a'    '' 
        ''     'f'
        'c'    'a'
    
    Aout = 
        'a'    'b'
        'a'    'b'
        'a'    'a'
        'c'    'a'
        'c'    'd'
        'a'    'd'
        'a'    'f'
        'c'    'a'
    

    方法 #2 [紧凑且可能更高效]

    您可以将输入元胞数组重塑为单列元胞数组,因此您无需遍历 元胞数组,这可能会导致更高效和更紧凑的代码 -

    %// Reshape all cells into a single columned cell array
    A1 = A(:);
    
    %// Rest of the code borrowed from previous approach with reshaping added
    %// at the end to bring the output back to the size of input array
    pos = ~cellfun('isempty', A1);
    [unq_str,~,str_idx] = unique(A1,'stable');
    Aout =  reshape(unq_str(changem(cumsum(pos),str_idx(pos),1:sum(pos))),size(A));
    

    奖励:changem 的自定义实现

    前面列出的代码使用需要 Mapping Toolboxchangem。所以,如果你有它,这里是它的一个定制版本,用bsxfunmax 实现,它只是发布在here 的早期解决方案代码的完善版本。这是自定义功能代码 -

    %// CHANGEM_CUSTOM  Home-cooked vesion of CHANGEM with MAX, BSXFUN
    function A  = changem_custom(A,newvals,oldvals)
    
    [valid,id] = max(bsxfun(@eq,A(:),oldvals(:).'),[],2); %//'
    A(valid) = newvals(id(valid));
    
    return;
    

    所以,要使用这个自定义函数替换changem,只需替换前面代码中的函数调用名称即可。

    【讨论】:

    • 优秀。感谢您的解决方案。今天我学习了新功能“changem”。
    • @nik 是的!事实上,我以前只看过一次,所以对我来说也很新鲜!
    • 哇! changem!凉爽的!如果我想替换矩阵中的多个条目,我总是用逻辑索引循环它。很高兴得知那里有一个便利功能。 +1
    • @rayryeng 在这种情况下,避免循环的方法很少,看看here
    • @nik 查看刚刚添加的奖励部分 :)
    【解决方案2】:

    此解决方案获取空单元格的索引并用前一个单元格的数据填充它。要填补更大的空白,需要多个步骤。

    ix=find(cellfun(@isempty,M))
    while numel(ix)>0, M(ix)=M(ix-1);ix=find(cellfun(@isempty,M)); end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-14
      • 2015-05-29
      • 2011-07-17
      • 1970-01-01
      • 2014-11-17
      • 2016-08-01
      • 1970-01-01
      相关资源
      最近更新 更多