Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
map1 = containers.Map({'212','2','12','44'},[4,5,6,7]);
keyset = str2double(keys(map1));

Now I do a set of operations on the keyset which will give back

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

I tired the following:

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

all of the above gave weird results in the final cell array. I just need the integers to be used as keys for another container map.

share|improve this question
1  
So what is your desired result? Is it {'203', '2', '12', '39'}? –  Eitan T Dec 30 '12 at 11:45

3 Answers 3

up vote 8 down vote accepted

I propose 5 additional solutions, three of which are 4-5x faster by than the solutions proposed so far. The lessons learned from this are:

  • num2str is slow
  • cellfun and arrayfun can add significant overhead
  • There are many ways to convert a numeric array to a cell array of strings.

The three highest-performance solutions are very similar in terms of performance:

Looping to assign cell elements

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

Converting all to string and calling textscan

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

Converting all to string and calling regexp.

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

Here's the full test code with timings:

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
share|improve this answer
    
+1 for the regexp solution and the details! –  Shai Dec 31 '12 at 6:23
    
Yay, mine is the slowest! But how did we end up talking about performance here? :-) –  Eitan T Dec 31 '12 at 7:19
    
@EitanT: It wasn't me! It was Shai who started it. –  Jonas Dec 31 '12 at 14:54
    
Just got the license server back. It works out great.. previously I also tried using sprintf('%11.0g',x). Thanks a lot.. –  martin Dec 31 '12 at 16:45

How about:

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

which should yield a 4-by-1 cell array for your example:

ans = 
    '203'
    '2'
    '12'
    '39'
share|improve this answer
    
please see my edited answer. Thanks. –  Shai Dec 30 '12 at 12:21
    
@Shai not sure that the OP is looking for performance in this case. –  Eitan T Dec 30 '12 at 12:24
    
this is why I added the "note" at the bottom - your solution is more "Matlab"ish than mine, but at a small cost of run-time... –  Shai Dec 30 '12 at 12:26
    
@Shai I don't think it's more "Matlab"ish :) it's just shorter (and currently slower) –  Eitan T Dec 30 '12 at 12:28
1  
I am particularly font of all the *fun function: cellfun, arrayfun, strcutfun etc. I think they are more "Matlab"ish than evaluating an "on the fly" string... But maybe that's just me. Anyhow, +1 for nice solution. –  Shai Dec 30 '12 at 12:34

How about:

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

I'm not sure this is the most elegant way to achieve the desired results, but it seems to work...

Comparing runtime with Eitan's solution:

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

Yields:

t =
   0.3986
   2.2527

It seems like proposed solution is faster.

Note: it seems like current implementation of cellfun is not optimized for speed. It is rumored that in future versions Mathworks intends to introduce better implementation of cellfun. So, Eitan's solution might not be optimal in current version, but it seems to be a good practice of Matlab skills.

share|improve this answer
    
+1: Even though your solution employs eval, it's still fast. However, I wonder if it works for very large arrays. By the way, I believe that 0.3s differs from 2.2s by approx. one order or magnitude (not two). –  Eitan T Dec 30 '12 at 13:53
    
@EitanT - oops. corrected. –  Shai Dec 30 '12 at 13:57
    
It is very difficult not to give you a -1 for an evil solution. Fortunately, there are at least 3 solutions that are faster. –  Jonas Dec 31 '12 at 0:15
    
@Jonas I hope you mean eval rather than evil... –  Shai Dec 31 '12 at 6:22
1  
The slip of tongue was not by chance... :) –  Eitan T Dec 31 '12 at 9:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.