How to use the values of an array as inputs for a function?

62 views (last 30 days)
Hi there, I have this function:
function [ spectralLevels ] = getJEVesselSpectrum( vesselClass, frequency_Hz, speed_kts, ...
length_m, getDdecSPLs, includeStdDev)
...
and I have a cell array (10x6) with inputs (rows in the array), i.e, I need 10 values (each row one value).
How do I loop through the rows' values to be the inputs of the function?
Thank you in advance!

Accepted Answer

dpb
dpb on 4 Sep 2022
Well, it would be easier if the function were written to accept an array instead of the six different variables -- but, you can work around it.
Firstly, if it really is a 10x6 cell array with each cell containing a single value (as it would appear from your description), that would be something like
>> c=num2cell(rand(10,6))
c =
10×6 cell array
{[0.5570]} {[0.2583]} {[0.8382]} {[0.7520]} {[0.9780]} {[0.6684]}
{[0.0703]} {[0.1176]} {[0.6008]} {[0.0056]} {[0.6803]} {[0.0495]}
...
That's not at all convenient if so -- turn it back into an ordinary array (or don't create the cell array to begin with)..
c=cell2mat(c); % get regular double array from cell array
outputs=arrayfun(@(i) getJEVesselSpectrum(c(i,1),c(i,(2),c(i,(3),c(i,(4),c(i,(5),c(i,(6)),[1:size(c,1)].');
This is the same thing as an explict for..end loop over the rows of the c array, passing each row in turn to your function.
If the output sectralLevels is a single value (likely not from the name?) then the above will return an array of length size(c,1) or 10 in this case. If it returns more than a single level, then you need (and it will chide you if do)
outputs=arrayfun(@(i) getJEVesselSpectrum(c(i,1),c(i,(2),c(i,(3),c(i,(4),c(i,(5),c(i,(6)),[1:size(c,1)].', ...
'UniformOutput',0);
and the output will be another cell array.
  2 Comments
Ana
Ana on 4 Sep 2022
Is there a better way than an array? Table, matrix? if so, how would the same thing be done?
dpb
dpb on 5 Sep 2022
Edited: dpb on 5 Sep 2022
"Better way" at what point?
As long as the function is written to accept six variables you'll have to pass six variables into it, whether they're held in an array or table or whatever; or create and mess with six different variables elsewhere.
Which might be "better" is a lot in the eye of the beholder, but also strongly dependent upon how these variables are generated. Where did the cell array come from, would be a starting point to ask.
If you change the calling sequence of the function to
function spectralLevels=getJEVesselSpectrum(vesselData, includeStdDev)
then you've got two variables (I'm guessing the latter is a flag logical variable, NOT actual data, based on the name). Inside the function you then will have something like
function [ spectralLevels ] = getJEVesselSpectrum(vesselData, includeStdDev)
vesselClass =vesselData(:,1);
frequency_Hz=vesselData(:,2);
speed_kt=vesselData(:,3);
length_m=vesselData(:,4);
getDdecSPLs=vesselData(:,5);
...
and the internal code carries on with the same variable names as before, you've just moved the conversion from array to individual variables inside the function where the user doesn't see it.
The other way to approach such things is to write the function so that it is vectorized internally to accept (either the various variables or the fewer alternative above) as vectors/arrays and does the looping internally. This is "the MATLAB way" and would then behave similarly as do almost all the builtin functions. The looping still occurs, but then it, too, is moved out of the top level code where it's handled transparently to the caller.

Sign in to comment.

More Answers (1)

Paul
Paul on 5 Sep 2022
Assuming the function resturns a scalar ....
Will a simple loop suffice?
c = num2cell(rand(10,6));
y = zeros(size(c,1),1);
for ii = 1:numel(y)
y(ii) = getJEVesselSpectrum(c{ii,:});
end
y
y = 10×1
2.7984 2.0398 2.9261 3.9852 3.3230 3.8970 3.8507 3.1624 2.3417 2.6782
Or w/o the loop
y = cellfun(@(x) getJEVesselSpectrum(x{:}),mat2cell(c,ones(size(c,1),1)))
y = 10×1
2.7984 2.0398 2.9261 3.9852 3.3230 3.8970 3.8507 3.1624 2.3417 2.6782
function [ spectralLevels ] = getJEVesselSpectrum( vesselClass, frequency_Hz, speed_kts, ...
length_m, getDdecSPLs, includeStdDev)
% made up function
spectralLevels = sum([vesselClass,frequency_Hz, speed_kts, ...
length_m, getDdecSPLs, includeStdDev]);
end
  4 Comments
dpb
dpb on 5 Sep 2022
Edited: dpb on 5 Sep 2022
@Paul's function is, as he says, totally made up -- if the variables are of different types then an ordinary array of doubles doesn't work as the argument variable, true. That would require a cell array but maybe then that's an indication to rethink the data storage and consider using a table which can hold disparate data types and has a great deal of functionality built into it that might be useful in whatever is actually being done with said data; that part we "know nuthink!" about so don't have the benefit of that knowledge to add context.
A struct array might be another alternative, but would not be my first choice in all likelihood; they have some less-than-appealing ways needed to use them although there are cases they're ideal for, too.
In short, we don't have enough background information to be able to give unequivical answer; can only provide guidance/suggestions within general MATLAB coding best practices.
Paul
Paul on 5 Sep 2022
As noted, we are just really guessing about what's contained in the elements of c and have just been illustrating methods assuming that all of the those elements are scalars. If, as noted as a possibility, the elements of c are all different types and sizes (typical use case for a cell array), the the mehod(s) shown here of generating a comma separated list from each row of c will still work.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!