2

I have a cell array A [1x80] in which each element is a cell array itself [9x2]. I have also a vector B representing a group of selected cells of A and I want to extract the element {2,2} of each selected cell.

I tried with a simple

A(1,B){2,2}

but of course it doesn't work.... Can you help me?

Amro
  • 123,847
  • 25
  • 243
  • 454
gabboshow
  • 5,359
  • 12
  • 48
  • 98
  • Since you said cell array in cell array, shouldn't you try `A{1,B}{2,2}` instead, and if that doesn't work `tmp = A{1,B}; tmp{2,2}`? – Tobias Kienzler Aug 22 '13 at 13:11
  • @TobiasKienzler tmp = A{1,B} returns just the cell corresponding to the first element of B. – gabboshow Aug 22 '13 at 13:16
  • if B is [1 3 5] I would like to have the element {2,2} of A{1,1}, A{1,3} and A{1,5}... – gabboshow Aug 22 '13 at 13:17
  • 1
    I think your problem is accessing the upper cell as `()`, where it should be `{}`. If you use `()` it returns the cell itself, not the elements inside the cell. – Werner Aug 22 '13 at 13:34

3 Answers3

3

How about this:

A = {{1 2; 3 4}, {5 6;7 8}, {9 0; 1 2}; {3 4; 5 6}, {7 8; 9 0}, {11 22; 33 44}};
B = [2,3]

[cellfun(@(x)x(2,2), A){1, B}]

ans =

   8   2

EDIT:

The above actually only works in octave. As @Amro points out, to modify it to work in Matlab you need to use a temporary variable:

temp = cellfun(@(x)x(2,2), A);
[temp{1, B}]

or in a one liner (also thanks to @Amro)

cellfun(@(c)c{2,2}, A(1,B))
Dan
  • 45,079
  • 17
  • 88
  • 157
  • 1
    I think that will error in MATLAB, you need to use a temporary variable in that last statement: `c = cellfun(@(x)x(2,2), A); [c{1,B}]` – Amro Aug 23 '13 at 05:02
  • @Amro I just tested it, you're right! Once again I was foiled by testing in Octave. – Dan Aug 23 '13 at 06:18
2

How about arrayfun(@(x) A{1,x}{2,2}, B)
or (thanks @Amro) cellfun(@(c)c{2,2}, A(1,B))?

Tobias Kienzler
  • 25,759
  • 22
  • 127
  • 221
  • 1
    @Dan Ah, true, your answer uses cellfun to obtain each cell's `{2,2}` element and accesses the `(1,B)` elements, mine the other way around. I wonder which one performs better... But that probably depends on the dimensions and sub-dimensions – Tobias Kienzler Aug 22 '13 at 13:25
  • If this were Python, the answer would be more understandable: `[A[1][b][2][2] for b in B]` – Tobias Kienzler Aug 22 '13 at 13:32
  • Well if the OP is concerned with efficiency, it's easy enough to test. But more likely he/she should just choose whichever seems more intuitive to him/her. They're very similar otherwise – Dan Aug 22 '13 at 13:37
  • @TobiasKienzler: similarly: `cellfun(@(c)c{2,2}, A(1,B))` – Amro Aug 23 '13 at 05:12
  • @Amro I'd say so too, but OP [states](http://stackoverflow.com/questions/18381366/access-predefined-elements-of-cells/18381652?noredirect=1#comment26992670_18381366) `A(1,B)` (shouldn't it be `A{1,B}`?) would only return `A(1,B(1))`. I don't have MATLAB any more, so I cannot verify this though – Tobias Kienzler Aug 23 '13 at 06:50
  • Ah, I see [Dan checked that](http://stackoverflow.com/questions/18381366/access-predefined-elements-of-cells/18381652?noredirect=1#comment27017998_18381656) already, so I'll edit it in. But probably the temp-var issue also applies for my `arrayfun`-solution, or does that work directly? – Tobias Kienzler Aug 23 '13 at 07:32
  • 1
    @TobiasKienzler: no need for temp vars, both solutions work in MATLAB and Octave. btw if you need quick access to Octave (which is for most cases same as MATLAB), try [ideone.com](http://ideone.com/S43UNt) – Amro Aug 23 '13 at 13:45
2

This answer is the same as @Dan's, but using a simple for loop for performance improvement, if needed.

% If you know that the numel of elements returned by {2,2} will always be one:
nElem = numel(B);
ret(1,nElem)=0;

for k=1:nElem

  ret(k) = A{1,B(k)}{2,2}

end

The following answer is wrong, it will only return the {2,2} index from the first element from B

subsref([A{1,B}],struct('type','{}','subs',{{2,2}}))

Which sounds more like what you are doing (and doesn't uses cellfun and arrayfun, that would be better if you are doing this operation on a loop, because they are slow)

See subsref documentation here.

A longer path would be:

temp = [A{1,B}]
temp{2,2}
Community
  • 1
  • 1
Werner
  • 2,537
  • 1
  • 26
  • 38
  • 1
    I only get the {2,2} element of the first element in `B` using both of your methods... (i.e. run on my sample `A` and `B` that I posted in my solution I get `ans = 8`, don't get the `2`) – Dan Aug 22 '13 at 13:49
  • @Dan Yeah, but if `B` is big, you will make a big loop using the `cellfun` which would not be very fast. The subsref is the matlab builtin function for sub-referencing a element… – Werner Aug 22 '13 at 13:52
  • @Dan ah ok, let me check it – Werner Aug 22 '13 at 13:53
  • @Dan yeah you are right, there may be a way to fix the subsref for accessing each element, but I think what he needs is a loop, if he wants performance he can make a `for` loop to access, otherwise he can use `cellfun` for convenience as in your answer x) – Werner Aug 22 '13 at 14:01