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

現在我做了一套在專用話機操作,這將給回Matlab的:轉換一個雙矢量數組字符串單元陣列

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

我厭倦了以下內容:

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

以上所有都在最後的單元陣列中給出了奇怪的結果。我只需要將整數用作另一個容器映射的鍵。

+2

那麼,什麼是你想要的結果?它是'{'203','2','12','39'}'? –

回答

13

我提出5個額外的解決方案,其中三個是快4-5倍而不是迄今爲止提出的解決方案。從中學到的教訓是:

  • num2str緩慢
  • cellfunarrayfun可以添加顯著開銷
  • 有很多方法的數值數組轉換爲字符串的單元陣列。

三個最高性能的解決方案在性能方面非常相似:

循環分配電池元件

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 
+0

爲'regexp'解決方案和細節+1! – Shai

+0

耶,我是最慢的!但是我們怎麼最終在這裏談論表演呢? :-) –

+0

@EitanT:那不是我!是Shai開始的。 – Jonas

3

如何:

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

我不知道這是最優雅的方式來達到預期的效果,但它似乎工作...

與埃坦的解決方案相比運行時間:

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技能​​實踐。

+0

+1:即使您的解決方案使用了「eval」,它仍然很快。不過,我想知道它是否適用於非常大的數組。順便說一下,我相信'0.3s'與'2.2s'的區別大約是。一個訂單或量級(而不是兩個)。 –

+0

@EitanT - 哎呀。糾正。 – Shai

+0

很難不給你一個'邪惡'解決方案-1。幸運的是,至少有三種解決方案更快。 – Jonas

7

如何:

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

應該產生一個4×1單元陣列爲你的例子:

ans = 
    '203' 
    '2' 
    '12' 
    '39' 
+0

請看我編輯的答案。謝謝。 – Shai

+0

@Shai不確定OP是否在這種情況下尋找性能。 –

+0

這就是爲什麼我在底部添加「註釋」 - 你的解決方案是更多的「Matlab」比我的,但在一個小運行時間的成本... – Shai

0

想出如何提高大整數的正則表達式的解決方案,使用拆分功能。 另外我被Jonas的一個解決方案誤導了一點,它沒有評估for循環中的所有sprintf調用。 編輯:也添加了評論中建議的新的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 
+0

從16b開始MATLAB有一個字符串數據類型。字符串(Keyset)比最快的情況快25%。 – matlabbit

+1

我最初的實驗是使用tmp4 = string(Keyset)導致現有tmp4的破壞。當使用一個新的變量時,字符串(Keyset)比最快的情況快40%。 – matlabbit