syntax for creating array of cell arrays

  • Follow


This might be simple and I'm just slow today:
I need an array, actors, of structs, with the field globalPose which will contain a (1,12) numeric array. I create the struct initially with
actors=struct('globalPose',cell(1,nbActrors));
at this point my structure exists, but the field is an empty 0x0 numeric array. I would now have to change the size of the content of this field in a loop, which is not ideal. Ideally, I would like to create the struct such that it initially contains a 1x12 array of zeros in the field globalPose of each of its elements. Is there a way to do this in a call to struct()?
Thanks,
-naor
0
Reply Naor 11/15/2010 8:20:05 PM

On 10-11-15 02:20 PM, Naor Movshovitz wrote:
> This might be simple and I'm just slow today:
> I need an array, actors, of structs, with the field globalPose which
> will contain a (1,12) numeric array. I create the struct initially with
> actors=struct('globalPose',cell(1,nbActrors));
> at this point my structure exists, but the field is an empty 0x0 numeric
> array. I would now have to change the size of the content of this field
> in a loop, which is not ideal. Ideally, I would like to create the
> struct such that it initially contains a 1x12 array of zeros in the
> field globalPose of each of its elements. Is there a way to do this in a
> call to struct()?

actors = struct('globalPose', repmat({zeros(1,12)},1,nbActors));

Note, though, that this particular approach will likely result in each cell 
member originally pointing to the _same_ 1 x 12 array of zeros, with 
copy-on-write enabled. At execution time when you are storing actual values in 
the arrays, this would be slower than if you managed to initialize the entries 
to _different_ 1 x 12 arrays of zeros. Personally, unless nbActors was fairly 
large or the program was going to be used a *lot*, I wouldn't worry about 
that, feeling that the code simplicity would probably make up for the minor 
increase in execution time beyond the theoretical minimum.

If you want to initialize to different 1 x 12 arrays of zeros, then the 
cleanest (but not necessarily most efficient) code might be to use

actors = struct('globalPose', ...
mat2cell(zeros(nbActors,12), ones(nbActors,1), 12) );

or something close to that.
0
Reply Walter 11/15/2010 8:36:19 PM


 [actors(1:nbActors).globalPose]=deal(zeros(1,12));
0
Reply Matt 11/15/2010 8:37:04 PM

One way:

s = struct('globalPose',repmat({zeros(1,12)},1,nbActrors))

Another way

 s=struct('globalPose',cell(1,nbActrors))
[s.globalPose]=deal(zeros(1,12))

Bruno
0
Reply Bruno 11/15/2010 8:42:04 PM

Thanks Walter! The reason I'm concerned about pre-allocation here is that my execution time seems to increase non-linearly with nbActors. I don't know for sure if this is due to changing the size of each globalPose during assignment. I will try both your approaches.
-naor
Walter Roberson <roberson@hushmail.com> wrote in message <ibs5k6$m1t$1@canopus.cc.umanitoba.ca>...
> On 10-11-15 02:20 PM, Naor Movshovitz wrote:
> > This might be simple and I'm just slow today:
> > I need an array, actors, of structs, with the field globalPose which
> > will contain a (1,12) numeric array. I create the struct initially with
> > actors=struct('globalPose',cell(1,nbActrors));
> > at this point my structure exists, but the field is an empty 0x0 numeric
> > array. I would now have to change the size of the content of this field
> > in a loop, which is not ideal. Ideally, I would like to create the
> > struct such that it initially contains a 1x12 array of zeros in the
> > field globalPose of each of its elements. Is there a way to do this in a
> > call to struct()?
> 
> actors = struct('globalPose', repmat({zeros(1,12)},1,nbActors));
> 
> Note, though, that this particular approach will likely result in each cell 
> member originally pointing to the _same_ 1 x 12 array of zeros, with 
> copy-on-write enabled. At execution time when you are storing actual values in 
> the arrays, this would be slower than if you managed to initialize the entries 
> to _different_ 1 x 12 arrays of zeros. Personally, unless nbActors was fairly 
> large or the program was going to be used a *lot*, I wouldn't worry about 
> that, feeling that the code simplicity would probably make up for the minor 
> increase in execution time beyond the theoretical minimum.
> 
> If you want to initialize to different 1 x 12 arrays of zeros, then the 
> cleanest (but not necessarily most efficient) code might be to use
> 
> actors = struct('globalPose', ...
> mat2cell(zeros(nbActors,12), ones(nbActors,1), 12) );
> 
> or something close to that.
0
Reply Naor 11/15/2010 9:02:05 PM

ah the deal function, I forgot about that one. Thanks for the reminder :)
-naor
"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <ibs5ur$mj8$1@fred.mathworks.com>...
> One way:
> 
> s = struct('globalPose',repmat({zeros(1,12)},1,nbActrors))
> 
> Another way
> 
>  s=struct('globalPose',cell(1,nbActrors))
> [s.globalPose]=deal(zeros(1,12))
> 
> Bruno
0
Reply Naor 11/15/2010 9:03:04 PM

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <ibs5ur$mj8$1@fred.mathworks.com>...
>
>  s=struct('globalPose',cell(1,nbActrors))
> [s.globalPose]=deal(zeros(1,12))

Is there a reason to prefer the 2-line solution to be prefered over the 1-liner

 [actors(1:nbActors).globalPose]=deal(zeros(1,12)); 

as I'd proposed? Is it a matter of pre-allocation?
 
0
Reply Matt 11/15/2010 9:09:03 PM

On 10-11-15 03:03 PM, Naor Movshovitz wrote:
> ah the deal function, I forgot about that one. Thanks for the reminder :)

Note that deal() will, in this instance, result in the _same_ array of zeros 
being shared (copy on write) between all the structure members.
0
Reply Walter 11/15/2010 9:18:17 PM

will deal(rand(1,12)) instead of deal(ones(1,12)) result in different arrays created? I can't tell with my test data b/c the extra run time of rand() may be offsetting the benefit of pre-allocating.

Walter Roberson <roberson@hushmail.com> wrote in message <ibs82q$p4s$1@canopus.cc.umanitoba.ca>...
> On 10-11-15 03:03 PM, Naor Movshovitz wrote:
> > ah the deal function, I forgot about that one. Thanks for the reminder :)
> 
> Note that deal() will, in this instance, result in the _same_ array of zeros 
> being shared (copy on write) between all the structure members.
0
Reply Naor 11/15/2010 9:24:04 PM

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <ibs7hf$7j7$1@fred.mathworks.com>...
> "Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <ibs5ur$mj8$1@fred.mathworks.com>...
> >
> >  s=struct('globalPose',cell(1,nbActrors))
> > [s.globalPose]=deal(zeros(1,12))
> 
> Is there a reason to prefer the 2-line solution to be prefered over the 1-liner
> 
>  [actors(1:nbActors).globalPose]=deal(zeros(1,12)); 
> 

Personally I prefer the two line solutions because it erase any existing variable 's' (if any). At least 100% sure it create nbActors structures with single field.

The one-line syntax is at the merci of any existing 's' (it might be larger in size, it might have other fields, it might trow out an error of s exists but is not a structure). I have encountered few bugs of that type.

Question of preference and good coding discipline.

Bruno
0
Reply Bruno 11/15/2010 9:26:05 PM

On 10-11-15 03:24 PM, Naor Movshovitz wrote:
> will deal(rand(1,12)) instead of deal(ones(1,12)) result in different
> arrays created?

Unfortunately, no. When you deal a numeric array, the entire array is copied 
(shared) to the outputs.

repmat({zeros(1,12)},1,nbActors) creates shared numeric arrays because what 
gets copied by repmat() is the cell array with its intact pointer to the 
numeric array. This is in contrast to rempat(zeros(1,12), 1, nbActors)
which would be the same as zeros(1, 12*nbActors) with all the zeros unshared: 
copies of numeric values that are made are not shared with each other.

repmat()'ing rand(1,12) will not help as the larger array you would end up 
would not be broken up in to cells. repmat({rand(1,12)},...) would create the 
single cell first and then copy that single cell with its one set of numeric 
values.

There are shorter syntaxes you can use with (e.g.) arrayfun

T = arrayfun(@(K) {zeros(1,12)}, 1:nbActors);
[s(1:nbActors).globalPose] = deal(T{:});

This would give a different array each time, at the expense of some obscurity. 
Possibly more efficient than my mat2cell suggestion, but that would need to be 
timed to be sure. Incidentally, the mechanism the above two lines uses to work 
_cannot_ be merged into a single statement -- a Matlab limitation.
0
Reply Walter 11/15/2010 9:50:06 PM

"Naor Movshovitz" <nmovshov@gmail.com> wrote in message <ibs8dk$5i2$1@fred.mathworks.com>...
> will deal(rand(1,12)) instead of deal(ones(1,12)) result in different arrays created? I can't tell with my test data b/c the extra run time of rand() may be offsetting the benefit of pre-allocating.

ATTENTION: Preallocating within struct (and cell) might not needed (thus a waste), depending how later you intend to use the arrays.

If you elaborate how the array is intended to be used later (do you change element by element? Do you change the whole array? ...) we might advise you what is the good way to initialize the structure.

Bruno
0
Reply Bruno 11/15/2010 10:03:03 PM

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message 
> ATTENTION: Preallocating within struct (and cell) might not needed (thus a waste), depending how later you intend to use the arrays.
> 
> If you elaborate how the array is intended to be used later (do you change element by element? Do you change the whole array? ...) we might advise you what is the good way to initialize the structure.
> 
> Bruno

Here is what my first attempt looked like, mostly ignoring efficiency and focusing on clarity. 
I create a new struct tree with field actors:
tree.actors=struct('globalPose',cell(1,nActors),...
                          'otherfields',cell(1,nActors);
Now to fill up with useful data:
for k=1:nActors
   gPose=calculatesomething. % gPose is a 1x12 numeric array now
   tree.actors(k).globalPose=gPose;
end

As I said, I am not sure why this does not scale well with nActors. I would be grateful for any suggestions, not just pre-allocation. Thanks!
-naor
0
Reply Naor 11/15/2010 10:28:04 PM

"Naor Movshovitz" <nmovshov@gmail.com> wrote in message <ibsc5j$cin$1@fred.mathworks.com>...
> "Bruno Luong" <b.luong@fogale.findmycountry> wrote in message 
> > ATTENTION: Preallocating within struct (and cell) might not needed (thus a waste), depending how later you intend to use the arrays.
> > 
> > If you elaborate how the array is intended to be used later (do you change element by element? Do you change the whole array? ...) we might advise you what is the good way to initialize the structure.
> > 
> > Bruno
> 
> Here is what my first attempt looked like, mostly ignoring efficiency and focusing on clarity. 
> I create a new struct tree with field actors:
> tree.actors=struct('globalPose',cell(1,nActors),...
>                           'otherfields',cell(1,nActors);
> Now to fill up with useful data:
> for k=1:nActors
>    gPose=calculatesomething. % gPose is a 1x12 numeric array now
>    tree.actors(k).globalPose=gPose;
> end
> 
> As I said, I am not sure why this does not scale well with nActors. I would be grateful for any suggestions, not just pre-allocation. Thanks!

If  tree.actors(k).globalPose is later set in for-loop as showed, then you can forget preallocation altogether. It is useless. Simply initialize your structure array with empty field.

Bruno
0
Reply Bruno 11/15/2010 10:35:04 PM

You were right Bruno. Pre-allocating didn't help. I found that limited Java memory prevented this script from scaling well. I am staring a new thread looking for help on this issue. Thanks,
-n

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <ibscio$97b$1@fred.mathworks.com>...
> "Naor Movshovitz" <nmovshov@gmail.com> wrote in message <ibsc5j$cin$1@fred.mathworks.com>...
> > "Bruno Luong" <b.luong@fogale.findmycountry> wrote in message 
> > > ATTENTION: Preallocating within struct (and cell) might not needed (thus a waste), depending how later you intend to use the arrays.
> > > 
> > > If you elaborate how the array is intended to be used later (do you change element by element? Do you change the whole array? ...) we might advise you what is the good way to initialize the structure.
> > > 
> > > Bruno
> > 
> > Here is what my first attempt looked like, mostly ignoring efficiency and focusing on clarity. 
> > I create a new struct tree with field actors:
> > tree.actors=struct('globalPose',cell(1,nActors),...
> >                           'otherfields',cell(1,nActors);
> > Now to fill up with useful data:
> > for k=1:nActors
> >    gPose=calculatesomething. % gPose is a 1x12 numeric array now
> >    tree.actors(k).globalPose=gPose;
> > end
> > 
> > As I said, I am not sure why this does not scale well with nActors. I would be grateful for any suggestions, not just pre-allocation. Thanks!
> 
> If  tree.actors(k).globalPose is later set in for-loop as showed, then you can forget preallocation altogether. It is useless. Simply initialize your structure array with empty field.
> 
> Bruno
0
Reply Naor 11/17/2010 9:02:04 PM

14 Replies
313 Views

(page loaded in 0.068 seconds)

Similiar Articles:


















7/23/2012 5:31:40 PM


Reply: