8
map1 = containers.Map({'212','2','12','44'},[4,5,6,7]);
keyset = str2double(keys(map1));

今、私はキーセットに対して一連の操作を行います。

Keyset= [203,2,12,39];

私は次のことに疲れました:

num2cell(num2str(keyset));
num2cell(num2str(keyset,1));
num2cell(num2str(keyset,'%11.0g'));
num2cell(num2str(keyset,3));

上記のすべては、最終的なセル配列で奇妙な結果をもたらしました。別のコンテナマップのキーとして使用する整数が必要です。

4

4 に答える 4

13

私は5つの追加ソリューションを提案しますが、そのうち3つは、これまでに提案されたソリューションよりも4〜5倍高速です。これから学んだ教訓は次のとおりです。

  • num2str遅い
  • cellfunarrayfunかなりのオーバーヘッドを追加する可能性があります
  • 数値配列を文字列のセル配列に変換する方法はたくさんあります。

3つの最高パフォーマンスのソリューションは、パフォーマンスの点で非常に似ています。

セル要素を割り当てるためのループ

n4 = length(Keyset);
tmp4 = cell(n4,1);
for i4 = 1:n4
    tmp4{i4} = sprintf('%i',Keyset(i4));
end

すべてを文字列に変換して呼び出すtextscan

tmp6 = textscan(sprintf('%i\n',Keyset'),'%s');
tmp6 = tmp6{1};

すべてを文字列に変換して呼び出しregexpます。

tmp3 = regexp(sprintf('%i ',Keyset),'(\d+)','match');

タイミングを含む完全なテストコードは次のとおりです。

function t = speedTest

t=zeros(7,1);
for ii=1:100, 
    Keyset=randi(1,10,100); % random keys
    tic; 
    eval( [ 'tmp1 = { ', sprintf(' %d ', Keyset), ' }; '] );
    t(1)=t(1)+toc; 
    tic;
    tmp2=arrayfun(@num2str, Keyset, 'Uniform', false);
    t(2)=t(2)+toc;

    tic;
    tmp3 = regexp(sprintf('%i ',Keyset),'(\d+)','match');
    t(3) = t(3)+toc;

    tic;
    n4 = length(Keyset);
    tmp4 = cell(n4,1);
    for i4 = 1:n4
        tmp4{i4} = sprintf('%i',Keyset(i4));
    end
    t(4) = t(4)+toc;

    tic;
    n5 = length(Keyset);
    tmp5 = cell(n5,1);
    for i5 = 1:n5
        tmp4{i5} = num2str(Keyset(i5));
    end
    t(5) = t(5)+toc;

    tic;
    tmp6 = textscan(sprintf('%i\n',Keyset'),'%s');
    tmp6 = tmp6{1};
    t(6) = t(6)+toc;

    tic;
    tmp7 = num2cell(Keyset);
    tmp7 = cellfun(@(x)sprintf('%i',x),tmp7,'uni',false);
    t(7) = t(7)+toc;


end;
t

t =

    1.7820
   21.7201
    0.4068
    0.3188
    2.2695
    0.3488
    5.9186
于 2012-12-31T00:13:04.453 に答える
7

どうですか:

arrayfun(@num2str, Keyset, 'Uniform', false)'

これにより、例として4行1列のセル配列が生成されます。

ans = 
    '203'
    '2'
    '12'
    '39'
于 2012-12-30T12:06:49.617 に答える
3

どうですか:

eval( [ 'NewKeySetStr = { ', sprintf(' %d ', Keyset), ' }; '] );
NewKeySetStr

これが望ましい結果を達成するための最もエレガントな方法かどうかはわかりませんが、うまくいくようです...

ランタイムとEitanのソリューションの比較:

t=zeros(2,1);
for ii=1:100, 
    Keyset=randi(1,10,100); % random keys
    tic; 
    eval( [ 'NewKeySetStr = { ', sprintf(' %d ', Keyset), ' }; '] );
    t(1)=t(1)+toc; 
    tic;
    tmp=arrayfun(@num2str, Keyset, 'Uniform', false);
    t(2)=t(2)+toc;
end;
t

収量:

t =
   0.3986
   2.2527

提案された解決策の方が速いようです。

注:の現在の実装はcellfun速度が最適化されていないようです。将来のバージョンでは、Mathworksはのより良い実装を導入する予定であると噂されていますcellfun。したがって、Eitanのソリューションは現在のバージョンでは最適ではない可能性がありますが、Matlabスキルの優れた実践であるように思われます。

于 2012-12-30T11:53:56.997 に答える
0

分割機能を使用して、大きな整数の正規表現ソリューションを改善する方法を理解しました。また、forループ内のすべてのsprintf呼び出しを評価しなかった、Jonasのソリューションの1つに多少誤解されました。編集:コメントで提案された新しい2016文字列機能も追加しました。

t = speedTest()

function t = speedTest

t=zeros(5,1);
for ii=1:100
    Keyset=randi(10000000,10,1000); % random keys

    tic;
    n4 = numel(Keyset); % changed to numel (length only gives number of columns)
    tmp1 = cell(n4,1);
    for i4 = 1:n4
        tmp1{i4} = sprintf('%i',Keyset(i4));
    end
    t(1) = t(1)+toc;

    tic;
    tmp2 = regexp(sprintf('%i ',Keyset),'(\d+)','match');
    t(2) = t(2)+toc;

    tic;
    tmp3 = regexp(sprintf('%i ',Keyset),' ','split');
    tmp3(end) = [];
    t(3) = t(3)+toc;

    tic;
    tmp4 = string(Keyset(:));
    t(4) = t(4)+toc;

    # test in case you want to go back to characters
    tic;
    tmp5 = char(string(Keyset(:)));
    t(5) = t(5)+toc;
end
end

分割を使用した正規表現ソリューションでは、パフォーマンスがわずかに向上し、文字列メソッドはさらに高速になります。

t =

    6.1916
    1.1292
    0.8962
    0.6671
    0.7523
于 2017-11-30T12:42:36.790 に答える