Matlab: Converting a double vector array to string cell array
Solution 1
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 slowcellfun
andarrayfun
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
Solution 2
How about:
arrayfun(@num2str, Keyset, 'Uniform', false)'
which should yield a 4-by-1 cell array for your example:
ans =
'203'
'2'
'12'
'39'
Solution 3
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.
martin
Updated on July 29, 2022Comments
-
martin almost 2 years
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.