struct problem when dealing with different field types

I created a struct containing variables of length 'n' (numeric) in separate fields: mystruct = struct('field1',variable_1,'field2', variable_2, ...)
everything works fine and I can type mystruct.field1 and it shows the values of variable_1 from 1:n:
ans =
32 2 22 1 1 2 ...n
If I type mystruct.field1(1) I get 32. This is good.
Now I want to include a variable which is a character cell in the struct, also of length n (n cells of differing sizes). When I add this variable to the struct, all the fields change to cells (I think), and I have to type mystruct (1).field1(1) to see 32. This is bad.
Is there a way to implement a cell in a struct without changing everything to cell? Or, is there a way to make a char string into something besides a cell to be stored into struct?
I tried changing the ascii chars into a binary stream and using bin2dec to turn into the dec equivalent for use in the struct, the problem is that this only works for shorter strings. If the string is too long, the decimal equivalent is too big for Matlab to handle.
Any ideas?

3 Comments

Please post the exact code you used to "... add this variable to the struct ..."
You can certainly add a cell array to a struct without changing the struct itself to a cell array by simply putting it under a different field name. But we need to see your code in order to advise you how to correct things.
OK, so here is what I am doing..
I have a large loop which parses a binary file and defines variables:
for i = 1:n
variable1(i) = bin2dec(binaryfile(1:4)) %%bytes 1-4
variable2(i) = bin2dec(binaryfile(5:8))
...
variableX(i) = {char(binaryfile(30:50))}
end
%
mystruct = ('field1',variable1, ...)
most variables are a decimal representation of 4 bytes from a large data file (I merge the 4 bytes into one 32bit binary stream first, then bin2dec it). The problem is that there are a couple variables that are 20 bytes (160 bits), which is too large to change to decimal.
When I comment out the "variableX" line in the above code, I get a struct of length "1" containing variables of length "n". When I keep the "variableX" line in, I get a struct of length "n" with variables of length "n" as well.
I'd like to keep everything in decimal form as many variables will be plotted from the struct.
See Per's solution using the { } wrapper for the cell array of strings. E.g., for your case:
mystruct = struct('field1',variable1, ... ,'fieldX',{variableX})

Sign in to comment.

 Accepted Answer

"implement a cell in a struct" &nbsp I'm not sure I understand.
Hint:
>> sas = struct('vec',[1:12],'string','abcdefgh','cellstr',{{'abc123','def456'}})
sas =
vec: [1 2 3 4 5 6 7 8 9 10 11 12]
string: 'abcdefgh'
cellstr: {'abc123' 'def456'}
>> sas.structure = struct('f1',1,'s1','a' )
sas =
vec: [1 2 3 4 5 6 7 8 9 10 11 12]
string: 'abcdefgh'
cellstr: {'abc123' 'def456'}
structure: [1x1 struct]
>>

9 Comments

Isakson, try your above code, but do this:
cellstr(1:5) = {'asdf'}
sas = struct('vec',[1:12],'string','abcdefgh','cellstr',cellstr)
sas ends up as a 1x5 struct array, when what I want is a struct with cellstr of length 1x5.
Note that Per has wrapped his cell array of strings within another level of { }, making the input a scalar cell array. That will prevent the behavior you are seeing and don't want.
I noticed that, doesn't seem to do anything different. Try this:
m(1:5) = 1
n(1:5) = 32
p(1:5) = {{'blah'}}
s = struct('m',m,'n',n,'p',p)
s = 1x5 struct array (bad)
now leave off the p field:
g = struct('m',m,'n',n)
The result is
g =
m: [2 2 2 2 2]
n: [34 34 34 34 34]
This is the result I want (but including "p"
That's because you didn't do what we said! p is still a vector cell array and that is what you passed into the struct function! You need to pass it in as Per has indicated using a { } wrapper, making that last argument a scalar cell array. E.g., do this instead:
s = struct('m',m,'n',n,'p',{p})
I see you have to put {} in the actual structure definition to get this to work.
I actually dynamically assign the structure definition based on the variables that are created, which makes this solution difficult. my code to dynamically define the structure is as follows (I use "who" to find all existing variables before my code, then "who" again afterwords. Then I diff the two and the result is "new_var_list" or all the variables I created)
[len,wid] = size(new_var_list);
struct_construct = '';
for structnum = 1:len
clear varname
varname = strrep(new_var_list(structnum,:),' ','');
struct_construct = strcat(struct_construct,sprintf('''%s'',%s,',varname,varname));
end
struct_construct = strrep(strcat('(',struct_construct,')'),',)',')');
evalstr = sprintf('%s = struct%s;',MESSAGE_NAME,struct_construct);
eval(evalstr);
"struct_construct" ends up being the string of "('fieldname1',variable1,...)" for all variables created. I'm not sure how to add "{}" around only some of the variables that are cells... Any ideas to get this to work outside of that solution?
nevermind, I got it. A simple "if iscell" call in the above loop fixes everything. Thanks
IMO: the documentation of struct requires a second reading to understand how the dimension of the created structure is controlled by a cell array of cell arrays. Here is more examples
>> s = struct('m',m,'n',n, 'p',{repmat({'bla'}, 1,5 )} )
s =
m: [1 1 1 1 1]
n: [32 32 32 32 32]
p: {'bla' 'bla' 'bla' 'bla' 'bla'}
and
>> p(1,1:5) = {'blah'};
>> s = struct('m',m,'n',n, 'p',{p} )
s =
m: [1 1 1 1 1]
n: [32 32 32 32 32]
p: {'blah' 'blah' 'blah' 'blah' 'blah'}
Well, you could find out if varname is a cell array and then take appropriate steps as you see fit. E.g.,
var_is_cell = eval(['iscell(' varname ')']);
if( var_is_cell )
varadd = ['{' varname '}'];
else
varadd = varname;
end
struct_construct = strcat(struct_construct,sprintf('''%s'',%s,',varname,varadd));
Or you could put in code to actually change the variable in question to a scalar cell array:
if( var_is_cell )
eval([varname '={' varname '}']);
end
But this is getting ugly, isn't it? Are you sure you want to go down this route of generating struct's with fieldnames that are defined from strings in real-time? How are you planning on dealing with this downstream in your code? More sprintf's and eval's? This is going to be a real headache down the road for you to manage the code for readability and maintainability.
yes, maintainability may be an issue, luckily I do know beforehand which variables will be what types. Thanks for all the input

Sign in to comment.

More Answers (0)

Categories

Asked:

Art
on 10 Apr 2015

Edited:

on 16 May 2015

Community Treasure Hunt

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

Start Hunting!