使用基于索引 MATLAB 的元素填充元胞数组
Fill cell array with elements based on the indices MATLAB
我有一个 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'];
它运行良好,但我想知道最佳解决方案?
假设 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
that needs Mapping Toolbox
. So, if you do have it, here's a customized version of it, implemented with bsxfun
and max
and is merely a polished version of an earlier solution code posted 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
,只需替换前面代码中的函数调用名称即可。
此解决方案获取空单元格的索引并用前一个单元格的数据填充它。要填补更大的空白,需要多个步骤。
ix=find(cellfun(@isempty,M))
while numel(ix)>0, M(ix)=M(ix-1);ix=find(cellfun(@isempty,M)); end
我有一个 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'];
它运行良好,但我想知道最佳解决方案?
假设 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
that needs Mapping Toolbox
. So, if you do have it, here's a customized version of it, implemented with bsxfun
and max
and is merely a polished version of an earlier solution code posted 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
,只需替换前面代码中的函数调用名称即可。
此解决方案获取空单元格的索引并用前一个单元格的数据填充它。要填补更大的空白,需要多个步骤。
ix=find(cellfun(@isempty,M))
while numel(ix)>0, M(ix)=M(ix-1);ix=find(cellfun(@isempty,M)); end