以下函数适用于任意数组,具有任何嵌套结构和任何形状的数组,只要它们都是二维数组。多维数组不受支持(与
mat2str
相同)。
该函数还允许为单元格数组指定任意行和列分隔符(例如,选择逗号和空格之间的差异),并可选地强制非单元格数组使用这些分隔符(从而覆盖
mat2str
的行为)。单元格数组中的默认分隔符为列使用
' '
,行使用
'; '
。
function y = array2str(x, col_sep, row_sep, sep_noncell)
if nargin<4
sep_noncell = false;
end
if nargin<3
row_sep = '; ';
end
if nargin<2
col_sep = ' ';
end
x = {x};
y = {[]};
done = false;
while ~done
done = true;
for n = 1:numel(y);
if isempty(y{n})
done = false;
if ~iscell(x{1})
s = mat2str(x{1});
if sep_noncell
s = regexprep(s,'(?<=^[^'']*(''[^'']*'')*[^'']*) ', col_sep);
s = regexprep(s,'(?<=^[^'']*(''[^'']*'')*[^'']*);', row_sep);
end
y{n} = s;
x(1) = [];
else
str = ['{' repmat([{[]}, col_sep], 1, numel(x{1})) '}'];
ind_sep = find(cellfun(@(t) isequal(t, col_sep), str));
if ~isempty(ind_sep)
str(ind_sep(end)) = [];
ind_sep(end) = [];
end
step_sep = size(x{1}, 2);
str(ind_sep(step_sep:step_sep:end)) = {row_sep};
y = [y(1:n-1) str y(n+1:end)];
x = [reshape(x{1}.', 1, []) x(2:end)];
end
end
end
end
y = [y{:}];
上述函数使用正则表达式来强制非单元数组中指定的分隔符。这在Matlab中有效,但在Octave中无效,因为支持的反向查找模式受限。以下修改后的版本避免了正则表达式,因此在Matlab和Octave中均有效。与第一个版本相比,只有if sep_noncell
和匹配的end
之间的部分发生了变化。
function y = array2str(x, col_sep, row_sep, sep_noncell)
if nargin<4
sep_noncell = false;
end
if nargin<3
row_sep = '; ';
end
if nargin<2
col_sep = ' ';
end
x = {x};
y = {[]};
done = false;
while ~done
done = true;
for n = 1:numel(y);
if isempty(y{n})
done = false;
if ~iscell(x{1})
s = mat2str(x{1});
if sep_noncell
for k = flip(find(~mod(cumsum(s==''''),2) & s==' '))
s = [s(1:k-1) col_sep s(k+1:end)];
end
for k = flip(find(~mod(cumsum(s==''''),2) & s==';'))
s = [s(1:k-1) row_sep s(k+1:end)];
end
end
y{n} = s;
x(1) = [];
else
str = ['{' repmat([{[]}, col_sep], 1, numel(x{1})) '}'];
ind_sep = find(cellfun(@(t) isequal(t, col_sep), str));
if ~isempty(ind_sep)
str(ind_sep(end)) = [];
ind_sep(end) = [];
end
step_sep = size(x{1}, 2);
str(ind_sep(step_sep:step_sep:end)) = {row_sep};
y = [y(1:n-1) str y(n+1:end)];
x = [reshape(x{1}.', 1, []) x(2:end)];
end
end
end
end
y = [y{:}];
它是如何工作的
我选择了一种非递归方法,因为我通常比递归更喜欢迭代。
输出是通过在单元数组(y
)中保留子字符串或空数组([]
)来逐步构建的。单元格数组y
中的空数组表示“需要进一步处理”。子字符串定义了“结构”,或最终嵌套单元格的最深层次中的数字、字符或逻辑内容。
在每次迭代中,y
中找到的第一个空数组被实际内容或子字符串和其他空数组替换以供稍后处理。当y
不包含任何空数组时,该过程结束,并将y
的所有子字符串连接起来以获得最终字符串输出。
例如,给定输入x={[10 20], {'abc'; false; true;}};
并调用y=array2str(x)
,则每个步骤中的数组y
都是一个包含以下内容的单元格数组:
'{' [] ', ' [] '}'
'{' '[10 20]' ', ' [] '}'
'{' '[10 20]' ', ' '{' [] '; ' [] '; ' [] '}' '}'
'{' '[10 20]' ', ' '{' ''abc'' '; ' [] '; ' [] '}' '}'
'{' '[10 20]' ', ' '{' ''abc'' '; ' 'false' '; ' [] '}' '}'
'{' '[10 20]' ', ' '{' ''abc'' '; ' 'false' '; ' 'true' '}' '}'
而后者最终被连接成字符串。
'{[10 20] {''abc''
作为具有自定义分隔符的示例,
array2str(x, ', ', '; ', true)
将返回:
'{[10, 20], {''abc''
reshape
而不是嵌套调用cat
。原因是 reshape 是一种非常便宜的操作,而多个cat
将导致大量的复制开销。 - carandraug