2015-03-12 3 views
2

Я пытаюсь создать строку аргумента для анонимной функции на основе количества входных аргументов без использования для циклов. Например, если N = 3, то я хочу строку, которая считываетMatlab - динамически создает строку для анонимной функции

@(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3)) 

Я попытался с помощью repmat ('топор', 1, N), но я не могу понять, как чередовать (I) индекс.

Любые идеи?

Кроме того, ответы на них до сих пор решены. Чтобы дать некоторую интуицию тем, кто задается вопросом , почему Я хочу сделать это: мне нужно построить очень большую матричную анонимную функцию (якобиан) порядка 3000x3000. Сначала я использовал функции Matlab jacobian и matlabFunction для построения анонимной функции; однако это было довольно медленно. Вместо этого, поскольку замкнутая форма производной была довольно простой, я решил создать анонимную функцию напрямую. Это было сделано путем формирования символьной матрицы Якобиана J, затем добавив ее к указанной выше строке @() с помощью char (J {:}) 'и используя eval для формирования окончательной анонимной функции. Это может быть не самое изящное решение, но я считаю, что он работает намного быстрее, чем комбинация jacobian/matlabFunction, особенно для больших N (кроме того, структура нового подхода позволяет проводить оценку параллельно).

EDIT: Просто для полноты, правильной формы аргумента строки для анонимной функции следует читать

@(ax1,ax2,ax3,ay1,ay2,ay3) 

избежать синтаксической ошибки, связанные с индексацией.

+1

Использование строки для этого не является отличным решением. Я подозреваю, что вы, возможно, захотите использовать 'varargin' вместо этого. Какие анонимные функции вы хотите построить точно? Во-вторых: Синтаксис, который вы создаете, недействителен в MATLAB. – knedlsepp

+0

В ожидании моего значка Mentalist я предсказываю, что OP действительно хочет что-то вроде этого: 'f = @ (ax, ay) ...', который затем будет вызываться через 'f ([a, b, c], [ d, e, f]) ' – knedlsepp

+0

Благодарим вас за разъяснение. Я до сих пор не понимаю, как ответы решают вашу проблему.Они просто создают синтаксическую ошибку, если вы используете на них 'str2func'. – knedlsepp

ответ

2

Я предлагаю следующее:

N = 3; 
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)]; 

functionString = sprintf(['@(',argumentString(1:end-1),')'], 1:N, 1:N) 

Во-первых, вы создаете маски ввода для sprintf (например, 'ax(%i)'), который затем заполняется соответствующими номерами для создания строки функции.

Примечание: синтаксис @(ax(1),...) на самом деле не работает. Скорее всего, вы хотите использовать либо @()someFunction(ax(1),...), либо пытаетесь передать несколько входных аргументов существующей функции, и в этом случае сохранение входов в массиве ячеек и вызов функции как fun(axCell{:}) будет работать.

+0

Я не получаю ответы на все вопросы. То, чего хочет ФП, не имеет никакого смысла !? – knedlsepp

+0

Привет, спасибо. Да, я планирую добавить функцию (в строковой форме) к указанному выше, а затем использовать eval() для получения моей анонимной функции. –

1

Попробуйте это:

N = 3; 
sx = strcat('ax(', arrayfun(@num2str, 1:N, 'uniformoutput', 0), '),'); 
sy = strcat('ay(', arrayfun(@num2str, 1:N, 'uniformoutput', 0), '),'); 
str = [sx{:} sy{:}]; 
str = ['@(' str(1:end-1) ')'] 
+0

Отлично, спасибо! Могу ли я спросить вас, что делает второй набор квадратных скобок в определении str? –

+0

Еще раз спасибо за ответ, но я обнаружил, что это приводит к некорректному выводу при N> 9. –

+1

@Erik Эти скобки не нужны. Я исправил это, а также он теперь работает для N> 9 –

1

Решение будет использовать arrayfun:

sx = strjoin(arrayfun(@(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ','); 
sy = strjoin(arrayfun(@(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ','); 
s = ['@(' sx ',' sy ')']; 

содержит

'@(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))' 

Бест,

+0

Привет, спасибо! К сожалению, у меня нет версии в моей версии Matlab. Это недавняя функция? Любой способ воспроизвести его с помощью других функций? –

+1

О, да, он появился в R2014b, я думаю. Я использую R2015a. У вас есть [эквивалент] (http://www.mathworks.com/matlabcentral/fileexchange/21710-string-toolkits/content/strings/strjoin.m) на Matlab Central, или вы можете использовать 'sprintf'as, описанные здесь [здесь] (http://www.mathworks.com/matlabcentral/answers/20043-function-for-concatenating-strings-with-delimiters). – Ratbert

Смежные вопросы