以编程方式获取有效的开关/案例值

cra*_*gim 5 matlab

当MATLAB扫描switch/case块中的案例时,它是否记住它跳过的值,是否可以访问该列表?我有一些长switch\case块的函数,我想让它们返回一个有效的案例值列表,如果他们做到这一点otherwise.例如,我有一个函数返回一组材料的光学常数.它目前有大约20种不同的材料,并且随着我考虑新的材料而不断增长.

我知道我可以蛮力它,只是重新输入所有的有效病例为单元阵列之下otherwise,并有功能抛出一个错误,并返回的有效响应列表,但没有错误或懒惰随着时间的推移匍匐在保持两个列表很有挑战性.

Pur*_*uit 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
Run Code Online (Sandbox Code Playgroud)

这在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
Run Code Online (Sandbox Code Playgroud)

这是使用结构数组存储数据的示例.有许多方法可以使用Matlab数据结构来存储这种数据,例如Map或单元数组.有关一个相当全面的列表,请参阅此问题的答案: MATLAB每次迭代更改矩阵的名称


Moh*_*nia 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
Run Code Online (Sandbox Code Playgroud)

现在,您只需添加一个cc;beforeswitch即可重置持久变量,并将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
Run Code Online (Sandbox Code Playgroud)

这打印出:

Allowed cases are:
b
c
    1.2000
     2
     1     1
     1     1
Run Code Online (Sandbox Code Playgroud)

有风险的解决方案:该解决方案可能违反了相当多的编程实践,但仍然可以作为一种黑客手段。假设您没有嵌套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
Run Code Online (Sandbox Code Playgroud)

然后如果你运行这样的代码

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
Run Code Online (Sandbox Code Playgroud)

它打印出来

Allowed cases are:
b
c
    1.2000
     2
     1     1
     1     1
Run Code Online (Sandbox Code Playgroud)