2015-01-31 91 views
1

我有n * m個單元陣列Cell_In元素:填充單元陣列與基於索引MATLAB

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']; 

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

回答

5

假設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

前面列出的代碼使用changem需要Mapping Toolbox。所以,如果你確實有這個問題,這裏有一個定製的版本,用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,只是在前面的代碼替換函數調用的名字在那裏。

+0

優秀。感謝您的解決方案。今天,我學習了新的功能「changem」。 – nik 2015-01-31 22:46:43

+0

@nik是的!事實上,我之前只看到過一次,所以它對我來說也很新穎! – Divakar 2015-01-31 22:47:21

+1

哇! 'changem'!涼!如果我想要替換矩陣中的多個條目,我總是使用邏輯索引來循環它。很高興知道這裏有一項便利功能。 +1 – rayryeng 2015-02-01 00:36:54

1

該解決方案獲取空單元格的索引並使用前一個數據填充它。爲了填補更大的空白,需要多個步驟。

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