当MATLAB扫描switch/case
块中的案例时,它是否记住它跳过的值,是否可以访问该列表?我有一些长switch\case
块的函数,我想让它们返回一个有效案例值列表,如果它们降到otherwise
。例如,我有一个函数返回一组材料的光学常数。它目前有大约20种不同的材料,并且随着我考虑新的材料而不断增长。
我意识到我可以强制它,只需将所有有效案例重新键入otherwise
下的单元格数组,并让函数抛出错误并返回有效响应列表,但保留两个列表随着时间的推移,没有错误或懒惰是一个挑战。
答案 0 :(得分:6)
澄清一下,听起来你要求做的事情如下:
value = 'z';
output = [];
switch value
case 'a'
output = 1.234;
case 'b'
output = 2.345;
case 'c'
output = 3.456;
otherwise
output = [];
disp('Please use one the the following values: a, b, c')
%It would be nice to auto-populate that string wouldn't it?
end
这在Matlab(或我所知的任何语言)中都不是直接可能的。
但是,如果您从switch / case语句转移到更加以数据为中心的代码设计,那么它就变得简单了。例如,上面的代码可以重写为:
%Setup (this can be preloaded and stored as persistent if too time consuming)
count = 1;
allvalues(count).name = 'a'; allvalues(count).value = 1.234; count = count+1;
allvalues(count).name = 'b'; allvalues(count).value = 2.345; count = count+1;
allvalues(count).name = 'c'; allvalues(count).value = 3.456; count = count+1;
%Lookup
value = 'z'; %Also try value = 'a'
maskMatch = strcmp({allvalues.name},value);
if any(maskMatch)
output = allvalues(maskMatch).value;
else
disp('Please use one of the following values:');
disp({allvalues.name});
end
这是使用结构数组存储数据的示例。有许多方法可以使用Matlab数据结构来存储这种数据,例如:地图或单元格数组。有关详细信息,请参阅此问题的答案:MATLAB Changing the name of a matrix with each iteration
答案 1 :(得分:3)
编辑:在收到我的第一个解决方案的迷人评论之后,我提出另一个需要在代码中进行更多编辑而不是第一个解决方案,但仍然比其他解决方案更少(将原始解决方案移至端):
让我们定义一个抓取值并将它们保存在持久变量中的函数
function list = cc(value)
persistent allCases
if isempty(allCases) || (nargin == 0 && nargout == 0)
allCases = {};
end
if nargin == 1,
allCases = [allCases value];
list = value;
end
if nargin == 0 && nargout == 1,
list = allCases;
end
end
现在您可以在cc;
之前添加switch
来重置持久变量并将case
语句中的所有值传递给函数并调用otherwise
中的函数部分阅读值:
a = 'a';
v = 'c';
cc;
switch a
case cc({'b' v 1.2})
%Multiple cases
case cc(2)
%number
case cc(ones(2))
%matrix
otherwise
disp('Allowed cases are:');
cellfun(@disp, cc);
end
打印出来:
Allowed cases are:
b
c
1.2000
2
1 1
1 1
风险解决方案:此解决方案可能违反了相当多的编程习惯,但仍然可以作为黑客攻击。假设你不有嵌套的switch
语句,那么你可以在otherwise
语句中调用这样的函数:
function allCases = getCases
st = dbstack('-completenames');
line = st(2).line;
fLines = importdata(st(2).file, sprintf('\n'));
switchLine = find(~cellfun(@isempty, ...
regexp(fLines(1:line-1), '^\s*switch\s', 'once')), 1, 'last');
otherwLine = find(~cellfun(@isempty, ...
regexp(fLines(1:line-1), '^\s*otherwise\s*$', 'once')), 1, 'last');
caseLines = fLines(switchLine+1:otherwLine-1);
casesStr = regexprep(caseLines(~cellfun(@isempty, ...
regexp(caseLines, '^\s*case\s', 'once'))), '^\s*case\s*', '');
casesCells = cell(size(casesStr));
for iCases = 1:numel(casesCells);
casesCells{iCases} = evalin('caller', casesStr{iCases});
end
allCases = [casesCells{:}];
end
然后,如果你运行这样的代码
a = 'a';
v = 'c';
switch a
case {'b' v 1.2}
%Multiple cases
case 2
%number
case ones(2)
%matrix
otherwise
disp('Allowed cases are:');
cellfun(@disp, getCases);
end
打印出来
Allowed cases are:
b
c
1.2000
2
1 1
1 1
答案 2 :(得分:2)
AFAIK,没有这样的机制。在特定情况下,有可能实现一些矢量化技巧,但通常说,不。
而且,如果仅从(记忆)效率的角度来看,实现类似的switch
也是一个坏主意(所有情况可能是巨大的矩阵)。
你可以将这种机制合并在一起:
% define all your cases in a cell
cases = {...
'case1', 'case2', ...};
% and switch on these cases
switch [condition]
case cases{1}
% implement 'case1'
case cases{2}
% implement 'case2'
...
otherwise
char(cases) % contains all cases
end
显然,你的获得一般性,你失去的可读性;个别案例现在不与相应代码在同一位置。另外,cases
内容的顺序很重要,[继续列出许多缺点] ......
总之,它不是很漂亮。
您可以自动构建列表:
cases = {};
% FIRST CASE
if strcmp([condition], 'case1')
% code for 'case1'
else % insert the case just checked for in the new list
cases{end+1} = 'case1';
end
% SECOND CASE
if strcmp([condition], 'case2')
% code for 'case2'
else % insert the case just checked for in the new list
cases{end+1} = 'case2';
end
... % etc.
您实际上仍在构建2个列表:if
- 语句中的一个“匿名”列表,以及cases
单元格数组中的一个。但每个“案例”仍然是一个单独的实体,案例条件按案例分组。
当然,你做会失去switch
的力量。
......还有更多的计划。所有可比较的,都具有相似的缺点。
我担心最好的方法就是与它一起生活并管理两个相同的列表。