Следующая функция работает для произвольных массивов с любой структурой вложенности и для любой формы массивов, если они все 2D-массивы. Многомерные массивы не поддерживаются (такие же, как mat2str
).
Функция также позволяет указывать произвольные разделители строк и столбцов для массивов ячеек (например, выбирать между запятой и пробелом) и необязательно форсировать эти разделители для неячеистых массивов (таким образом, переопределение поведения mat2str
»). Разделители по умолчанию в массивах ячеек ' '
для столбцов и '; '
для строк.
function y = array2str(x, col_sep, row_sep, sep_noncell)
% Converts a (possibly cell, nested) array to string representation
%
% Optional inputs col_sep and row_sep specify separators for the cell arrays.
% They can be arbitrary strings (but they should be chosen as per Matlab rules
% so that the output string evaluates to the input). Optional flag sep_noncell
% can be used to force those separators with non-cell arrays too, instead of
% the separators produced by mat2str (space and semicolon)
% Default values
if nargin<4
sep_noncell = false;
end
if nargin<3
row_sep = '; ';
end
if nargin<2
col_sep = ' ';
end
x = {x}; % this is to initiallize processing
y = {[]}; % [] indicates content unknown yet: we need to go on
done = false;
while ~done
done = true; % tentatively
for n = 1:numel(y);
if isempty(y{n}) % we need to go deeper
done = false;
if ~iscell(x{1}) % we've reached ground
s = mat2str(x{1}); % final content
if sep_noncell % replace mat2str's separators if required
s = regexprep(s,'(?<=^[^'']*(''[^'']*'')*[^'']*) ', col_sep);
s = regexprep(s,'(?<=^[^'']*(''[^'']*'')*[^'']*);', row_sep);
end
y{n} = s; % put final content...
x(1) = []; % ...and remove from x
else % advance one level
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)) = []; % remove last column separator
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)]; % mark for further processing...
x = [reshape(x{1}.', 1, []) x(2:end)]; % ...and unbox x{1},
% transposed and linearized
end
end
end
end
y = [y{:}]; % concatenate all strings
Вышеупомянутая функция использует регулярные выражения для принудительного задания указанных разделителей в массивах, отличных от ячеек. Это работает в Matlab, но не в Octave, из-за ограничений в поддерживаемых шаблонах lookbehind. Следующая модифицированная версия позволяет избежать регулярных выражений и, таким образом, работает в Matlab и Octave. Только часть между if sep_noncell
и соответствием end
изменяется относительно первой версии.
function y = array2str(x, col_sep, row_sep, sep_noncell)
% Converts a (possibly cell, nested) array to string representation.
% Octave-friendly version
%
% Optional inputs col_sep and row_sep specify separators for the cell arrays.
% They can be arbitrary strings (but they should be chosen as per Matlab rules
% so that the output string evaluates to the input). Optional flag sep_noncell
% can be used to force those separators with non-cell arrays too, instead of
% the separators produced by mat2str (space and semicolon)
% Default values
if nargin<4
sep_noncell = false;
end
if nargin<3
row_sep = '; ';
end
if nargin<2
col_sep = ' ';
end
x = {x}; % this is to initiallize processing
y = {[]}; % [] indicates content unknown yet: we need to go on
done = false;
while ~done
done = true; % tentatively
for n = 1:numel(y);
if isempty(y{n}) % we need to go deeper
done = false;
if ~iscell(x{1}) % we've reached ground
s = mat2str(x{1}); % final content
if sep_noncell % replace mat2str's separators if required
for k = flip(find(~mod(cumsum(s==''''),2) & s==' ')) % process
% backwards, because indices to the right will become invalid
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; % put final content...
x(1) = []; % ...and remove from x
else % advance one level
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)) = []; % remove last column separator
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)]; % mark for further processing...
x = [reshape(x{1}.', 1, []) x(2:end)]; % ...and unbox x{1},
% transposed and linearized
end
end
end
end
y = [y{:}]; % concatenate all strings
Я выбрал нерекурсивный подход, потому что я обычно более удобен с итерацией, чем с рекурсией.
Выход постепенно создается путем сохранения подстрок или пустых массивов ([]
) в массиве ячеек (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''; false; true}}'
. В качестве примера с пользовательскими разделителями , array2str(x, ', ', '; ', true)
даст
'{[10, 20], {''abc''; false; true}}'
Это действительно отражает то, что вы написали в своем классе машинописи Circle
.
Если вы хотите иметь доступ к атрибуту r
из Circle
, я не понимаю, почему у вас также есть личный атрибут.
Ваша модель должна быть просто:
export class Circle {
C: number;
r: number;
}
Насколько я понимаю, вы вычисляете значение для C
при установке r
. Похоже, ваш код верен, но было бы лучше, если вы измените C
на частный, поскольку вы не хотите получать к нему доступ, поскольку его значение вычисляется на основе r
.
export class Circle {
private C: number; // make C private
private _r: number;
set r(value: number) {
this.C=2*3.14*value;
this._r = value;
}
get r(): number {
return this._r;
}
}
Поскольку _r
является приватным, вы не сможете получить к нему доступ вне класса, и единственный способ изменить его - использовать r
.
Итак, я нашел то, что искал ... Если кто-то тоже гуглит это: https://stackblitz.com/edit/angular-mkncdh
вы определяете свойство, которое Вы хотите приватный, а затем установите его в enumerable = false, как вы можете видеть в circle.ts. Это стало немного сложнее, чем я хотел, но делает именно то, что я хочу. Теперь вы можете увидеть в выводе, что в ngModel есть только эти публичные свойства :)