2

So I have several structs that contains data that is used is a dozen or so scripts. The problem is that for each script I only need a handfull of variables and the rest I can ignore. I am using a massive amount of data (gigs of data) and MATLAB often gives me out of memory errors so I need to remove all unnecessary fields from the structs.

Currently I have a cell that contains all unneeded fields and then I call rmfield on the structs. But the fields in the structs often change and it is getting to be a pain to be constantly updating the list of unneeded fields. So is there a way to tell MATLAB to keep only those fields I want and remove everything else even if I don't know what everything else is?

Here is an example,

  • Struct 1 has: A, B, C, D, E fields
  • Struct 2 has: A, B, C, D, E, F fields
  • Struct 3 has: A, B, C, D, E, F, G, H, I fields

Sometimes Struct 3 might only have A thru G.

I want to keep only A, B, and C fields and remove all other data from all the structs.

Suever
  • 64,497
  • 14
  • 82
  • 101
Fred
  • 1,054
  • 1
  • 12
  • 32

5 Answers5

6

Here is one way to do it:

  1. Get the list of all fieldnames using fieldnames
  2. Remove the ones that you want to keep from the list
  3. Remove everything that is left in the list

Example

s.a=1
s.b=2
s.c=3
s.d='chitchat'

tokeep = {'a','b'}

f=fieldnames(s)

toRemove = f(~ismember(f,tokeep));

s = rmfield(s,[toRemove])
Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
  • So I tried that using fieldnames() but couldn't figure out how to remove that ones that I wanted. I used a regular expression to do a search and replace but then rmfield obviously didn't like my replacement. Do you have any other suggestions for removing the strings from the cell? – Fred Feb 01 '13 at 14:55
  • @DennisJaheruddin: I've shortened your example a bit. Hope you don't mind. – Jonas Feb 01 '13 at 15:31
1

You could copy your struct's desired fields to a new variable in a function.

function newVar = getABC(strct)
    newVar.A = strct.A;
    newVar.B = strct.B;
    newVar.C = strct.C;        
end

strct will not be copied in memory beacuse you will not be manipulating it.

MATLAB uses a system commonly called "copy-on-write" to avoid making a copy of the input argument inside the function workspace until or unless you modify the input argument. If you do not modify the input argument, MATLAB will avoid making a copy.

You can get newVar and then clear strct from memory.


Fred's generalized version:

function newVar = getFields(oldVar, desiredCell)
    for idx = 1:length(desiredCell)
    newVar.(desiredCell{idx}) = oldVar.(desiredCell{idx});
end
HebeleHododo
  • 3,620
  • 1
  • 29
  • 38
  • The struct may not be copied in the function workspace, but it must still be in memory in the main worspace. Therefor I think the minimum memory required is probably still the size of struct and newstruct. – Dennis Jaheruddin Feb 01 '13 at 15:14
  • @DennisJaheruddin yes, but after leaving the function `strct` can be immediately removed from memory. Thus, only `newStrct` will occupy memory. – HebeleHododo Feb 01 '13 at 15:19
  • 1
    I like it, I'm going to use it. Thanks! – Fred Feb 01 '13 at 15:52
  • 1
    In case anyone is intersted, I used the answer but modified it somewhat to make it more generic.
    `function newVar = getFields(oldVar, desiredCell)
    for i=1:length(desiredCell)
    newVar.(desiredCell{i}) = oldVar.(desiredCell{i});
    end`
    This allows me to pass in any cell of strings of the variables I care about and get the data out. Thanks for the tip HebeleHododo!
    – Fred Feb 01 '13 at 18:16
  • @Fred that is a nice generalization. I edited it into my post. – HebeleHododo Feb 04 '13 at 08:29
0

1) Let's say you a have a structure S

2) You want to keep only the first three fields of S and delete all the others

fieldsS = fieldnames(S);
S = rmfield(S,fieldsS(4:end));
lachioma
  • 11
  • 2
0

The rmfield method in MATLAB is rather slow, so when dealing with large structures it is best to avoid it.

This MATLAB file exchange item: kpfield is basically the inverse of rmfield and should work exactly as you require.

It converts the structure to a cell array before keeping only the required indices by creating a logical array based on whether the fields exist in the fieldnames or not. The modified cell array is then converted back to a structure.

Disclaimer: I have written kpfield as I came across exactly the same issue.

0

I had success loading the struct- physically deleting fields I wanted to remove and then resaving the struct.

Deleting fields in the workspace does not delete them from the original struct - so resaving is necessary.