MATLAB: альтернатива использованию 'eval' для оценки строки - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть несколько массивов символов в массиве ячеек, которые фактически представляют объявление структур MATLAB.Примерно так:

tmp{1} = 'testData.input = [1;2;3;4;5]'
tmp{2} = 'testData.output = [2;4;6;8;10]'

Мне нужно выполнить эти «команды» и в итоге создать соответствующую структуру.Я использую функцию eval в цикле for, и она работает.

numEntries = numel(tmp);
for i = 1 : numEntries
    eval(tmp{i});
end

Однако, это мучительно медленно.Я должен отметить, что реальные массивы символов очень велики и содержат более 3000 чисел.Кроме того, сам массив ячеек tmp содержит около 25 000 ячеек.Есть ли способ улучшить производительность, учитывая, что я не могу изменить входные данные, то есть tmp просто дается из внешнего источника?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Я не могу проверить, значительно ли он быстрее, используя только 2 строки, которые вы привели в качестве примера, но я ожидаю, что этот метод будет быстрее, когда число элементов tmp будет расти.

Идея состоит в том,чтобы записать все инструкции присваивания, содержащиеся в tmp, в текстовый файл (на самом деле .m файл), затем просто выполните файл .m.Для большого количества строк я бы ожидал, что это будет намного быстрее, чем многократный вызов eval в цикле.

Итак, это работает отлично с вашим примером tmp, в итоге вы получитеструктура testData в вашем рабочем пространстве.

%% Create an '.m' file containing all the assignment instructions from the cell array
tmpFile  = 'tmpFile2execute.m' ;
fidw = fopen( tmpFile , 'w' ) ;
fprintf(fidw,'%% Auto generated file\n'); % or any other header line you want, or none...
for i = 1 : numel(tmp) ;
    fprintf(fidw,'%s ;\n',tmp{i});
end
fclose(fidw) ;
% (optional) only to keep workspace tidy
clear i fidw tmpFile tmp 

%% Execute the file
tmpFile2execute ;

Расширяя идею, вы могли бы сделать это function вместо script, где вы могли бы добавить некоторую постобработку и вернуть результатв переменной, а не непосредственно в рабочей области, но вы должны увидеть, приносит ли базовая идея какое-либо улучшение скорости.

0 голосов
/ 13 декабря 2018

cellfun(@eval,tmp); несколько улучшит производительность по циклу.В противном случае вам может потребоваться написать собственный синтаксический анализатор (который может быть быстрее, если ожидается ограниченный тип ввода, например, только присвоение, например структура . some_field . some_other_subfield = [ some_array ];).

Обратите внимание, что eval - рискованная функция для использования (если мистер Мишеф пишет во входных данных что-то вроде !rm -Rf /, !del *.* или rmdir(matlabroot,'s') у вас может получиться большой беспорядок при оценке этих строк)

...