# Working with Arrays of Structures 30

Posted by **Loren Shure**,

Though I have covered this topic somewhat in the past, it seems like a good time to refresh the information. There are recent posts on the MATLAB newsgroup relating to this topic such as this one.

### Contents

### Original Question

Suppose I have a structure array and want to find all the entries with a value of 4, **without looping**, something like `[m,n] = find(f.h == 4)`.

f(1).h = [1 2 3 4]; f(2).h = [5 6 7 8]; try [m,n] = find(f.h == 4); end

Why can't I use the `find` statement directly? Let's take a look at the error message to understand.

lerr = lasterror; disp(lerr.message)

Error using ==> eq Too many input arguments.

Too many input arguments? What **is** `f.h`? For that matter, what exactly is `f` again?

f

f = 1x2 struct array with fields: h

`f` is a `struct` array, and `f.h` is a comma-separated list.

f.h

ans = 1 2 3 4 ans = 5 6 7 8

### Alternatives

To turn this list into a MATLAB construct I can use, I'd normally either wrap it inside `[]` or `{}`. If I wrap `f.h` inside `[]`, I lose the information about what is in the first element of `f` and what is in the second.

[f.h]

ans = 1 2 3 4 5 6 7 8

Wrapping `f.h` inside `{}`, I have a cell array to work with.

{f.h}

ans = [1x4 double] [1x4 double]

I still can't immediately use `find` or numeric functions on this array.

try [m,n] = find({f.h} == 4); end lerr = lasterror; disp(lerr.message)

Error using ==> evalin Undefined function or method 'eq' for input arguments of type 'cell'.

### Solution

What I'd like is a way to work with my struct, without writing too much code, without looping, that is ideally a pattern I
can reuse as my problem evolves. This is exactly what `arrayfun` was designed to help with. It works on each element of an array, and I need to just tell it what I want to operate on one
element, as well as telling `arrayfun` what array to work on.

Let's first find the values in the struct array `f` equal to 4. Since I have 2 arrays embedded in `f`, and they may each have different numbers of outputs, I have to clearly state that the outputs need to go into a cell array.

`[m,n] = arrayfun(@(x)find(x.h==4),f,'uniformoutput',false)`

m = [1] [1x0 double] n = [4] [1x0 double]

This becomes even more obvious if I can another array, `g` that is even less "regular" than `f`.

```
g = f;
g(3).h = [1 2 17 4];
g(4).h = [1 3 17 5 9 17];
[mg,ng] = arrayfun(@(x)find(x.h==17),g,'uniformoutput',false)
```

mg = [1x0 double] [1x0 double] [1] [1x2 double] ng = [1x0 double] [1x0 double] [3] [1x2 double]

Some problems are more benign however and it would be wasteful to return results in a cell array and then have to unpack them
into a numeric array, for example, the function `max`, which generally has a single value as the result.

[minval,idx] = arrayfun(@(x)max(x.h),f) [minval,idx] = arrayfun(@(x)max(x.h),g)

minval = 4 8 idx = 4 4 minval = 4 8 17 17 idx = 4 4 3 3

### Related Topics

Here are some links to related blogs and MATLAB reference pages.

### Your Thoughts

- Do you use struct arrays?
- If yes, do you use
`arrayfun`, or do you use loops? Whichever your choice is, can you say more about why it's your choice? - Do you avoid struct arrays all together and use something else? If so, what data representations do you use instead?

Let's see your feedback here.

Get the MATLAB code

Published with MATLAB® 7.3

**Category:**- Structures

### Note

Comments are closed.

## 30 CommentsOldest to Newest

**1**of 30

**2**of 30

**3**of 30

**4**of 30

**5**of 30

??? Error using ==> cat CAT arguments dimensions are not consistent.--Loren

**6**of 30

S.filtSize=[10,20,30]; S.name={’john’,'george’}; S.type={@hann}; [filtInd, nameInd, typeInd] = ndgrid(length(S.filtSize),length(S.name),length(S.type); filtInd = 1 1 2 2 3 3 nameInd = 1 2 1 2 1 2 typeInd = 1 1 1 1 1 1Using triplets of those indices gets you all the combinations of inputs. --Loren

**7**of 30

**8**of 30

`f`is a vector:

for i=1:numel(f) [ml{i} nl{i}] = find(f(i).h == 4) end isequal(m,ml) isequal(n,nl)--Loren

**9**of 30

**10**of 30

**11**of 30

**12**of 30

Undefined function or method 'eq' for input arguments of type 'cell'.I realize that's only a small portion of your comments but thought it was worth clarifying here. --Loren

**13**of 30

**14**of 30

**15**of 30

**16**of 30

??? Error using ==> eq Matrix dimensions must agree.Which points to the arrayfun function call Below is the code I'm using

all = [struct('name', 'HOLD_OFF', 'check', @(x)islogical(x)||isnumeric(x)) struct('name', 'FIGH', 'check', @isnumeric) struct('name', 'S', 'check', @ischar) struct('name', 'LINE_DIR', 'check', @ischar)]; c = arrayfun(@(x)find(x.name == varargin{1}), all, 'uniformoutput', false);varargin{1} contains the value 'FIGH' I've been staring at this error and googling for an answer for quite some time, but I still haven't found what is causing the error. Do you have any idea what is causing this error? Thanks -Thomas

**17**of 30

**18**of 30

**19**of 30

**20**of 30

**21**of 30

**22**of 30

f(1).h = [1 2 3 4]; f(2).h = [5 6 3 8]; [m,n] = arrayfun(@(x)find(x.h==3),f,'uniformoutput',false)Now that i have the indexes, how can I replace those "3" by, for example, 0? I mean without using loops. Thanks a lot in advance.

**23**of 30

**24**of 30

**25**of 30

**26**of 30

A = [1 2 3; 1 2 4] f(1).h = [1 2 5; 2 5 6; 1 2 3; 3 5 6] f(2).h = [1 2 6; 3 5 6; 1 5 3; 3 5 6] f(3).h = [1 2 4; 3 4 5; 1 1 3; 3 4 6] [m,n] = arrayfun(@(x)find(x.h==A),f,'uniformoutput',false)

**28**of 30

**29**of 30

**30**of 30

## Recent Comments