Assuming that
outputTemp =
2×1 cell array
{122×1 string}
{220×1 string}
finalOutput is a string array (342x1 string).
is there any way to do the following
outputTemp = arrayfun(#(x)someFunc(x), someInput, 'UniformOutput', false)';
finalOutput= [outputTemp{1}; outputTemp{2}];
in one line?
for the minimal example, someFunc can be a function that provides the names of the files in folders provided in someInput.
Short answer: yes. Here is a MWE:
str1 = ["Test";"Test1";"42"]
str2 = ["new test";"pi = 3"]
C = {str1;str2}
ConCatStr = [C{1};C{2}];
This should answer the question regarding concatnation of string-arrays. Note that this is only possible with real strings (not with char-arrays). It is hard to tell, what you are doing beforehand as there are not details about getFilesFilt() and mainFolderCUBX.
EDIT MVE for the updated question
% function that returns a matrix
fnc = #(x)[x,1];
% anonymous function that returns a vector
fnc2 = #(x)reshape(fnc(x),2,1)
tmp = arrayfun(#(x)fnc(x), rand(10,1),'UniformOutput',false)
Answer: there is no proper way. However, you can do a little bit of fiddling and force everything into a single line (making the code ugly and less efficient)
tmp = arrayfun(#(x)fnc(x), rand(10,1),'UniformOutput',false);
out = reshape(cell2mat(tmp),numel(cell2mat(tmp)),1);
just replace the tmp with what is written with it.
You can try the following code using cat() + subsref(), i.e.,
finalOutput= cat(1,subsref(arrayfun(#(x)someFunc(x), someInput, 'UniformOutput', false),struct('type', '{}', 'subs', {{:}})));
Example
S(1).f1 = rand(3,5);
S(2).f1 = rand(6,10);
S(3).f1 = rand(4,2);
cat(1,subsref(arrayfun(#(x) mean(x.f1)',S,'UniformOutput',false),struct('type', '{}', 'subs', {{:}})))
such that
ans =
0.89762
0.53776
0.42440
0.25272
0.58197
0.34503
0.40259
0.41792
0.43527
0.53974
0.49976
0.63342
0.36539
0.58541
0.57042
0.60914
0.60851
Related
I declared some variables comprising of simple row vectors which represents input parameters for another function. Within a loop these variables should be used and the result will be assigned to a structure.
Now, my question is how to best access the content of the predefined variables. I found a solution using eval. However, I often read that the usage of eval should be avoided. Apparently it's not best practice. So, what's best practice for my problem?
varABC = [1,2,3];
varDEF = [4,5,6];
varGHI = [7,8,9];
names = {'ABC','DEF','GHI'};
result = {'result1','result2','result3'};
for i = 1 : 3
varString = strcat('var',names{i});
test.(result{i}) = sum(eval(varString));
end
I would suggest rewriting your code a little bit
names = {'ABC','DEF','GHI'};
result = {'result1','result2','result3'};
option 1
% Use struct instead of a simple variable
var.ABC = [1,2,3];
var.DEF = [4,5,6];
var.GHI = [7,8,9];
for i = 1 : 3
test.(result{i}) = sum(var.(names{i}));
end
option 2
% Use dictionary
c = containers.Map;
c('ABC') = [1,2,3];
c('DEF') = [4,5,6];
c('GHI') = [7,8,9];
for i = 1 : 3
test.(result{i}) = sum(c(names{i}));
end
Suppose I have a series of strings such as:
a = '101010101010'
b = '010101'
c = '000101010'
is there a way in Matlab to concatenate them and produce the binary number 101010101010010101000101010?
Use the concatenation operator [ ], with horizontal concatenation , (vertical concatenation ; will fail here unless you reshape() into column vectors):
[a,b,c]
However, I suggest storing your variables in a cell array:
s = {'101010101010','010101', '000101010'};
[s{:}]
or
cat(2,s{:})
To concatenate strings, you could say:
out = [a b c];
Alternatively:
out = strcat(a,b,c);
Yet another way:
out = sprintf('%s', a,b,c);
I think that this should work:
res = [a,b,c]
or alternatively call
res = strcat(a,b,c)
or, yet
res = cat(2,a,b,c)
I was just wondering if there is a clean way to store a matrix after each iteration with a different name? I would like to be able to store each matrix (uMatrix) under a different name depending on which simulation I am on eg Sim1, Sim2, .... etc. SO that Sim1 = uMatrix after first run through, then Sim2 = uMatrix after 2nd run through. SO that each time I can store a different uMatrix for each different Simulation.
Any help would be much appreciated, and sorry if this turns out to be a silly question. Also any pointers on whether this code can be cleaned up would be great too
Code I am using below
d = 2;
kij = [1,1];
uMatrix = [];
RLABEL=[];
SimNum = 2;
for i =1:SimNum
Sim = ['Sim',num2str(i)] %Simulation number
for j=1:d
RLABEL = [RLABEL 'Row','',num2str(j) ' '];
Px = rand;
var = (5/12)*d*sum(kij);
invLam = sqrt(var);
u(j) = ((log(1-Px))*-invLam)+kij(1,j);
uMatrix(j,1) = j;
uMatrix(j,2) = u(j);
uMatrix(j,3) = kij(1,j);
uMatrix(j,4) = Px;
uMatrix(j,5) = invLam;
uMatrix(j,6) = var;
end
printmat(uMatrix,'Results',RLABEL,'SECTION u kij P(Tij<u) 1/Lambda Var')
end
There are really too many options. To go describe both putting data into, and getting data our of a few of these methods:
Encode in variable names
I really, really dislike this approach, but it seems to be what you are specifically asking for. To save uMatrix as a variable Sim5 (after the 5th run), add the following to your code at the end of the loop:
eval([Sim ' = uMatrix;']); %Where the variable "Sim" contains a string like 'Sim5'
To access the data
listOfStoredDataNames = who('Sim*')
someStoredDataItem = eval(listOfStoredDataNames {1}) %Ugghh
%or of you know the name already
someStoredDataItem = Sim1;
Now, please don't do this. Let me try and convince you that there are better ways.
Use a structure
To do the same thing, using a structure called (for example) simResults
simResults.(Sim) = uMatrix;
or even better
simResults.(genvarname(Sim)) = uMatrix;
To access the data
listOfStoredDataNames = fieldnames(simResults)
someStoredDataItem = simResults.(listOfStoredDataNames{1})
%or of you know the name already
someStoredDataItem = simResults.Sim1
This avoids the always problematic eval statement, and more importantly makes additional code much easier to write. For example you can easily pass all simResults into a function for further processing.
Use a Map
To use a map to do the same storage, first initialize the map
simResults = containers.Map('keyType','char','valueType','any');
Then at each iteration add the values to the map
simResults(Sim) = uMatrix;
To access the data
listOfStoredDataNames = simResults.keys
someStoredDataItem = simResults(listOfStoredDataNames{1})
%or of you know the name already
someStoredDataItem = simResults('Sim1')
Maps are a little more flexible in the strings which can be used for names, and are probably a better solution if you are comfortable.
Use a cell array
For simple, no nonsense storage of the results
simResults{i} = uMatrix;
To access the data
listOfStoredDataNames = {}; %Names are Not available using this method
someStoredDataItem = simResults{1}
Or, using a slight level of nonesense
simResults{i,1} = Sim; %Store the name in column 1
simResults{i,2} = uMatrix; %Store the result in column 2
To access the data
listOfStoredDataNames = simResults(:,1)
someStoredDataItem = simResults{1,2}
Just to add to the detailed answer given by #Pursuit, there is one further method I am fond of:
Use an array of structures
Each item in the array is a structure which stores the results and any additional information:
simResults(i).name = Sim; % store the name of the run
simResults(i).uMatrix = uMatrix; % store the results
simResults(i).time = toc; % store the time taken to do this run
etc. Each element in the array will need to have the same fields. You can use quick operations to extract all the elements from the array, for example to see the timings of each run at a glance you can do:
[simResults.time]
You can also use arrayfun to to a process on each element in the array:
anon_evaluation_func = #(x)( evaluate_uMatrix( x.uMatrix ) );
results = arrayfun( anon_evaluation_func, simResults );
or in a more simple syntax,
for i = 1:length(simResults)
simResults(i).result = evaluate_uMatrix( simResults(i).uMatrix );
end
I would try to use a map which stores a <name, matrix>.
the possible way to do it would be to use http://www.mathworks.com/help/matlab/map-containers.html
Using a combination of this question and this Mathworks help thing on comma sep. lists I came up with this ugly way to make my formatting arguments a little prettier:
formatting{1,1} = 'color'; formatting{2,1} = 'black';
formatting{1,2} = 'fontweight'; formatting{2,2} = 'bold';
formatting{1,3} = 'fontsize'; formatting{2,3} = 24;
xlabel('Distance', formatting{:});
But it's still kinda ugly...is there a way to unpack a structure into a bunch of arguments a la a Python dictionary to **kwargs?
For instance, if I had the (IMHO) cleaner structure:
formatting = struct()
formatting.color = 'black';
formatting.fontweight = 'bold';
formatting.fontsize = 24;
Can I just pass that in somehow? If I try directly (xlabel('blah', formatting), or formatting{:}, it craps out saying "Wrong number of arguments".
You are very close. Just switch to a 1-D cell array.
formatting = {'Color', 'Red', 'LineWidth', 10};
figure
plot(rand(1,10), formatting{:})
If you really want to use a struct for formatting arguments, you can unpack it to a cell array and use it like above.
formattingStruct = struct();
formattingStruct.color = 'black';
formattingStruct.fontweight = 'bold';
formattingStruct.fontsize = 24;
fn = fieldnames(formattingStruct);
formattingCell = {};
for i = 1:length(fn)
formattingCell = {formattingCell{:}, fn{i}, formattingStruct.(fn{i})};
end
plot(rand(1,10), formatting{:})
It's probably a good idea to do the struct unpacking a separate little function so you can reuse it easily.
You can convert your structure to cell array with this function:
function c = struct2opt(s)
fname = fieldnames(s);
fval = struct2cell(s);
c = [fname, fval]';
c = c(:);
Then
formatting = struct2opt(formattingStructure);
xlabel('Distance', formatting{:});
Is there a way that I get all the structure subsubfield values of a subfield in one line ? Something like this :
struct.field(1:end).field
If I understand your question aright, you want to collect all the fields of the second-level structure, with the name 'field', into a single output array. It doesn't quite meet your request for a one-liner, but you can do it like this:
a.field1.a = 1;
a.field1.b = 2;
a.field2.a = 3;
a.field2.b = 4;
result = [];
for x = fieldnames(a)'
result = horzcat(result, a.(x{:}).a);
end
The ending value of result is [1 3]
Simple Structure Example
aStruct.subField = struct('subSubField', {1;2;3;4})
So that
aStruct.subField(1).subSubField == 1
aStruct.subField(1).subSubField == 2
Etc. Then the values of the leaf nodes can be obtained via a one-liner as
valueLeafs = [aStruct.subField.subSubField];
Which can be checked via assert(all(valueLeafs == [1,2,3,4])).
Non-Scalar Structure Example
The above one-liner also works when the leaf node values are non-scalar such that they can be horizontally concatenated. For example
bStruct.subField = struct('subSubField', {[1,2];[3,4]})
valueLeafs_b = [bStruct.subField.subSubField]; % works okay
cStruct.subField = struct('subSubField', {[1,2];[3;4]})
valueLeafs_c = [cStruct.subField.subSubField]; % error: bad arg dims
Distinct Class Structure Example
The one-line solution given previously does not work whenever the leaf node values are different class since they cannot - in general, be concatenated. However, use of arrayfun and a tricky anonymous function typically provide the required indexing technique:
dStruct.subField = struct('subSubField', {[1;2];'myString'});
valueLeafs_d = arrayfun(#(x) x.subSubField, dStruct.subField, 'UniformOutput', false)