1

I need to find indices in cell array of structs. For example, given:

arr{1}.id = 015
arr{2}.id = 015
arr{3}.id = 015
arr{4}.id = 015
arr{5}.id = 037
arr{6}.id = 037
arr{7}.id = 037
arr{8}.id = 037
arr{9}.id = 037
arr{10}.id = 037
arr{11}.id = 040
arr{12}.id = 040
...

I need to find indices which correspond to id=037 only (indx = [5 6 7 8 9])

Is there a simple matlabish solution, without using loops and searching for each individual element?

5
  • Do you have a specific reason to use a cell array of structs? From the example data a struct array would be the better (faster) data structure. Commented Feb 10, 2016 at 10:40
  • @Daniel I import a large JSON database (a list of people with several attributes, which is highly nested). This is what I get as output (a cell array of structs) when using JSONlab. I am not happy either. Commented Feb 10, 2016 at 10:42
  • Okay, that probably means you have additional fields which are not the same for all elements? Does [arr{:}] succeed? Commented Feb 10, 2016 at 10:44
  • You are right: "Error using horzcat Number of fields in structure arrays being concatenated do not match. Concatenation of structure arrays requires that these arrays have the same set of fields." Commented Feb 10, 2016 at 10:46
  • This is pretty ugly way to work with database, but I need some workaround just to make my job done. I can implement a straightforward way of searching for indices, but I would like to learn new tricks or other neat ways of working with cell arrays of structs. Commented Feb 10, 2016 at 10:48

1 Answer 1

1

Vectorisation is the primary tool to avoid loops and write fast code. It can be used when applying the same operation to many elements of the same kind. While in this case you want the same operation, the elements are different. Using a loop (which cellfun is) is the only possibility.

>> find(cellfun(@(x)(x.id),arr)==37)

ans =

     5     6     7     8     9    10

With the application you described I expect you will repetedly use this line, to have at least clean code I recommend to use a function

>> cellfield=@(data,field)(cellfun(@(x)(x.(field)),data))

cellfield = 

    @(data,field)(cellfun(@(x)(x.(field)),data))

>> cellfield(arr,'id')

ans =

  Columns 1 through 8

    15    15    15    15    37    37    37    37

  Columns 9 through 12

    37    37    40    40
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Daniel, It's amazing solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.