簡體   English   中英

Matlab:將雙向量數組轉換為字符串單元格數組

[英]Matlab: Converting a double vector array to string cell array

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

現在我對keyset進行一組操作,這些操作將返回

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

我厭倦了以下幾點:

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

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

我提出了5個額外的解決方案,其中三個解決方案比目前提出的解決方案快4-5倍。 從中吸取的教訓是:

  • num2str很慢
  • cellfunarrayfun會增加很多開銷
  • 有許多方法可以將數值數組轉換為字符串的單元格數組。

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

循環分配單元格元素

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

將all轉換為字符串並調用textscan

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

將all轉換為字符串並調用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

怎么樣:

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

這應該為您的示例產生一個4乘1的單元格數組:

ans = 
    '203'
    '2'
    '12'
    '39'

怎么樣:

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技能​​的一個很好的實踐。

使用拆分功能找出如何改進大整數的正則表達式解決方案。 我也被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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM