Matlab: преобразование двойного векторного массива в массив строковых ячеек
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 ответов
Я предлагаю 5 дополнительных решений, три из которых 4-5x быстрее, чем решения, предложенные до сих пор. Из этого можно извлечь следующие уроки:--10-->
-
num2str
медленно -
cellfun
иarrayfun
может добавить значительные накладные расходы - существует много способов преобразования числового массива в массив ячеек строк.
три высокопроизводительных решения очень похожи с точки зрения производительности:
зацикливание на назначить элементы ячейки
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
Как насчет:
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.
выяснил, как улучшить решение regexp для больших целых чисел, используя функцию разделения. Кроме того, меня несколько ввело в заблуждение одно из решений Джонаса, которое не оценивало все вызовы sprintf в цикле for. Edit: также добавлена новая функциональность строки 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
решение regexp с разделением дает немного лучшую производительность, а строковый метод еще быстрее:
t =
6.1916
1.1292
0.8962
0.6671
0.7523