Разбить строку в массив ячеек по позициям - PullRequest
1 голос
/ 13 апреля 2019

У меня есть файл со строками известной длины, но без разделителя.

% What should be the result
vals = arrayfun(@(x) ['Foobar ', num2str(x)], 1:100000, 'UniformOutput', false);

% what the file looks like when read in
strs = cell2mat(vals);
strlens = cellfun(@length, vals);

Самый простой подход довольно медленный:

out = cell(1, length(strlens));
for i=1:length(strlens)
    out{i} = fread(f, strlens(i), '*char');
end % 5.7s

Чтение всего и последующее деление намного быстрее:

strs = fread(f, sum(strlens), '*char');
out = cell(1, length(strlens));
slices = [0, cumsum(strlens)];
for i=1:length(strlens)
    out{i} = strs(slices(i)+1:slices(i+1));
end % 1.6s

С мекс-функцией я могу снизить до 0,6 с, так что есть еще много возможностей для улучшения. Можно ли получить сопоставимую производительность с чистым Matlab (R2016a)?

Редактировать: казалось бы, идеальная mat2cell функция не помогает:

out = mat2cell(strs, 1, strlens); % 2.49s

1 Ответ

2 голосов
/ 19 апреля 2019

Ваш последний подход - прочитать все сразу и разделить потом - выглядит для меня довольно оптимально, и вот как я делаю такие вещи.

Для меня он работает примерно за 80 мсек, когда файл находится на локальном SSD как в R2016b, так и в R2019a, на Mac.

function out = scratch_split_strings(strlens)
%
% Example:
% in_strs = arrayfun(@(x) ['Foobar ', num2str(x)], 1:100000, 'UniformOutput', false);
% strlens = cellfun(@length, in_strs);
% big_str = cat(2, in_strs{:});
% fid = fopen('text.txt'); fprintf(fid, '%s', big_str); fclose(fid);
% scratch_split_strings(strlens);

t0 = tic;
fid = fopen('text.txt');
txt = fread(fid, sum(strlens), '*char');
fclose(fid);
fprintf('Read time: %0.3f s\n', toc(t0));

str = txt;
t0 = tic;
out = cell(1, length(strlens));
slices = [0, cumsum(strlens)];
for i = 1:length(strlens)
    out{i} = str(slices(i)+1:slices(i+1))';
end
fprintf('Munge time: %0.3f s\n', toc(t0));

end
>> scratch_split_strings(strlens);
Read time: 0.002 s
Munge time: 0.075 s

Вы вставили его в профилировщик, чтобы увидеть, что занимает ваше время здесь?

Насколько я знаю, нет более быстрого способа разбить один простой массив на подмассивы переменной длины с собственным M-кодом. Вы делаете это правильно.

...