Concatinating multiple function outputs
조회 수: 6 (최근 30일)
이전 댓글 표시
I have a few functions that each returns 3 output values, within a for loop using i as a counter. Is there a nice way to assign values, in the sense that i am currently using:
for i=1:n
[TestValues(i,1), assymp(1), names{1}] = ftesttype1(I(:,i),p,sign);
[TestValues(i,2), assymp(2), names{2}] = ftesttype2(I(:,i),p,sign);
...
end
As you can see i have manually labelled them 1 and 2 for their places. Is there a way such taht the output will automatically move to the right spot ? - Ie. after ftesttype1 has returned its values ftesttype2 will put them in the right place without me needing to specify that spot 2 is to be used in the vectors TestValues, assymp and names.
The thing is i have meaby 50 such functions and how many changes sort of often. So i have to manually retype some 150 numbers alot (and check that i have done so correctly).
Thanks ALOT in advance!
댓글 수: 4
Star Strider
2014년 4월 21일
Tough indeed!
You appear to be fluent with MATLAB, so I assume you have done everything you can to optimise this. I’m a bit confused by your statement about ‘ftesttype2 putting the values returned by ftesttype1 in the right place’. The loop subscripts in the array assignments should do this. Are you passing the outputs of testtype1 to testtype2? It doesn’t seem so from the argument list, but I’m confused.
채택된 답변
Sean de Wolski
2014년 4월 21일
편집: Sean de Wolski
2014년 4월 21일
If you have a cell array containing your function handles, you could perhaps use cellfun to do the work for you:
Very simple example:
clear C % important for dynamic preallocation
funs = {@sin,@cos}; % function handles
vals = rand(1,50)*2*pi; % example values to loop over
for ii = numel(vals):-1:1
% Build anonymous function for each value and evaluate all functions at that value storing the result in the iith row of C
C(ii,:) = cellfun(@(x)x(vals(ii)),funs,'UniformOutput',false);
end
note 1 This also gives you the advantage of not necessarily having to input each function name. You could perhaps use dir to scrape a "functions to use" directory and then str2func to build the cell array automatically.
note 2 You don't need to use cellfun, but could use a loop instead. The key takeway here is the cell array containing the functions.
댓글 수: 3
Sean de Wolski
2014년 4월 22일
I feel kinda icky writing code to do this since it seems like there must be a better global approach to your publishing goals. But it works :)
%%Example setup
funs = {@sin, @cos, @max, @(x,y,z)(x+y+z)}; % function handles
vals = rand(1,50)*2*pi; % example values to loop over
extra_inputs = {{[]};{[]};{2};{2, 10}}; % each row contains extras, empty rows for functions that don't have them
idXtra = ~cellfun(@(x)isempty(x{1}),extra_inputs(:,1)); % which have extras?
%%Some useful info
nVals = numel(vals);
nFuns = numel(funs);
C = cell(nVals,nFuns);
%%Engine
for ii = 1:nVals
% Loop over values
% Build anonymous function for each value and evaluate all functions at that value storing the result in the iith row of C
for jj = 1:nFuns
% Extract function jj
fjj = funs{jj};
% Decide what to do
if idXtra(jj)
% Append extra inputs (jjth row)
foo = @(x)feval(fjj,x,extra_inputs{jj}{:});
else
% No extras
foo = fjj;
end
% Call foo, save output to cell
C(ii,jj) = {foo(vals(ii))};
end
end
Now the reason I'm using feval like that is because I assume you're going to want to be able to change the extra inputs. If you aren't, you could build the anonymous functions to always accept only one input, x, and pass the rest in based on their value at creation. This would greatly simplify the process but would not be flexible to updating the extra inputs during run time.
For example:
@(x)(x+y+z)
Now y and z are static snapshots of whatever they are when you create this. Once again, it's a little cleaner but doesn't scale well at all.
추가 답변 (1개)
Walter Roberson
2014년 4월 20일
There is nothing in MATLAB similar to "use the above as an example".
Are all of the functions called the same way? If so then you can use
for K = 1 : 50 %build table of function handles
funtab{K} = str2fun(sprintf('ftesttype%d', K));
end
for i = 1 : n
for K = 1 : 50
TestValues(i, K), assymp(K), names{K}] = funtab{K}(I(:,i), p, sign);
end
end
댓글 수: 2
Walter Roberson
2014년 4월 21일
Using a function table can account for calling the same function multiple times: just have multiple entries with the same handle.
Likewise you can use a cell array to hold all of the different inputs. You can do part of the breaking up of I(:,i) automatically by using mat2cell()
It might possibly be more convenient to reorder the calls so all of the ones with the same structure are done together. If the output order makes a difference for the remainder of your code, you could reorganize the outputs after the call loop.
Categorize and parameterize the calls as much as feasible. You can, for example, have a table which looks something like
output_number call_variety function_index parameter1_index
where call_variety is an index that tells you which variety of call it is, in the sense of which variables need to be passed.
I have, for example, written table-driven decompilers that mapped machine code byte into an "instruction format" code that knew (e.g.) that the instruction was a immediate-to-register instruction with specific offset and bit length encoding the destination register and specific offset and bit length encoding the "immediate" value; other instruction formats coded for register-to-register or condition-code bits and so on. The "variety" in the table encoded which kind of situation the entry should be treated as.
참고 항목
카테고리
Help Center 및 File Exchange에서 Matrix Indexing에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!