5

MATLAB がswitch/caseブロック内のケースをスキャンするとき、スキップした値を覚えていますか? また、そのリストにアクセスできますか? switch\case長いブロックを持ついくつかの関数があり、otherwise. たとえば、材料の一連の光学定数を返す関数があります。現在、約 20 種類の素材があり、新しいものを検討しながら増えています。

私はそれをブルートフォースできることを認識し、すべての有効なケースを下のセル配列に再入力しotherwise、関数にエラーをスローさせて有効な応答のリストを返しますが、エラーや時間の経過とともに忍び寄る怠惰なしで両方のリストを維持します挑戦的です。

4

3 に答える 3

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

これは、構造体の配列を使用してデータを格納する例です。Map や cell 配列など、この種のデータを格納するために Matlab データ構造を使用する方法は多数あります。やや包括的なリストについては、次の質問への回答を参照してください: MATLAB Making the name of matrix with each iteration

于 2013-06-26T16:44:12.310 に答える
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;beforeを追加し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
于 2013-06-26T18:24:16.127 に答える
2

私の知る限り、そのようなメカニズムはありません。特定のケースでは、いくつかのベクトル化のトリックを実行できる可能性がありますが、一般的に言えば、できません。

そして、(メモリ)効率の観点からのみであれば、その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 つのリストを作成しています。1つはif-statements の「匿名」リストで、もう 1 つはcasesセル配列です。ただし、各「ケース」は依然として個別のエンティティであり、ケース条件はケースごとにグループ化されています。

もちろん、あなたの力を失いますswitch

...そして、さらに多くのスキームがあります。すべて同等であり、すべて同等の欠点があります。

残念ながら、ここに行く最善の方法は、それと一緒に暮らし、2 つの同一のリストを管理することです。

于 2013-06-26T16:49:20.463 に答える