Changing the values of multiple objects at once?

조회 수: 25 (최근 30일)
Nathan Bush
Nathan Bush 2017년 5월 12일
댓글: Bryan Krause 2023년 10월 11일
I have an array of objects with certain properties.
Is it possible to change the values of a certain property for all objects in the array at once (without looping through them) ?
I'd also like to be able to change the properties by adding a fixed value to all of them (in other words, performing an operation on a single property for all objects at once). Is this also possible without a for loop?
Apologies if this is very simple.
e.g Below is a simplified version of what I'm trying to achieve
classdef test < dynamicprops
properties
Value
end
methods
function emission = is_greater(input,obj)
a = rand;
emission = a < input;
end
end
end
%an array of the object
for i=1:1:10
objarray(i)=test
end
%the below does not work, but shows what I'm trying to do
objarray.Value = rand;
objarray.Value = objarray.Value + 0.6;
  댓글 수: 1
men8th
men8th 2019년 10월 30일
편집: men8th 2023년 3월 13일
Having faffed about with this for a bit now I can confirm that Guillaume's answer is the way to go. The functions deal() and num2cell() are what is needed.
What I have learnt since then though is that assignment using a for loop is actually significantly faster (at least for the cases I've tested using the performance testing framework) than converting to cell arrays and then assigning to cell arrays to the properties of the array of objects.
Finally, if performance is important, it is important to get the data structures right. Better to have a single object with array valued properties than an array of objects with scalar valued properties. In other words, if you are reading this page because you are looking for vectorisation type performance enhancements with object arrays, perhaps you should consider if a single object with array properties and vectorised methods might be better.

댓글을 달려면 로그인하십시오.

답변 (2개)

Guillaume
Guillaume 2017년 5월 12일
편집: Guillaume 2017년 5월 12일
You do not need to create a special set function or override any operator to assign values to a property of an array of objects. The syntax is however slightly obscure and awkward as you need to use temporary cell arrays for the values to assign.
%object creation
for i=1:1:10
objarray(i)=test
end
%assigning the same value to each object. Use deal:
[objarray.Value] = deal(0.5);
%assigning different values to each object.
%Convert array of values to cell array, then convert cell array to comma-separated list:
values = num2cell(rand(1, numel(objarray)));
[objarray.Value] = values{:};
%add a constant to each property.
%convert list of values to array. add value. convert array to cell array. convert cell array to comma-separated list:
values = num2cell([objarray.Value] + 0.6);
[objarray.Value] = values{:};
Unfortunately, you can't do the conversion to cell array and the conversion of cell array to comma separated list on the same line due to matlab chaining rules, num2cell(x){:} is a syntax error. So in most cases, you need at least two lines. As I said, it's a bit awkward.
  댓글 수: 6
Art
Art 2020년 5월 6일
Thanks, but I think this works only for setting all objects properties to the same value? In my case I have read all current position values of the objects, adjusted them by some amount, and now am trying to put back in the new positions.
For some reason the following code does not work:
OrigPos = get(ObHandles,'Position');
set(ObHandles,'Position',OrigPos);
I get the error:
Error using Matlab.graphics.primitive.Text/set
Error setting property "Position" of class 'Text':
Value must be a 2 or 3 element vector of numeric or logical type
Stephen23
Stephen23 2020년 5월 7일
편집: Stephen23 2020년 5월 7일
"but I think this works only for setting all objects properties to the same value?"
No, you missed the distinction that Steven Lord gave:
set(t, 'Color', 'r') % <- all objects use the same value
set(t, {'Color'}, color) % <- every object has its own value
% ^ ^ The cell array is significant!
Change your code to follow the example Steven Lord gave (and as explained in the set documentation):
set(ObHandles,{'Position'},OrigPos);
% ^ ^ you need these!

댓글을 달려면 로그인하십시오.


Adam
Adam 2017년 5월 12일
편집: Adam 2017년 5월 12일
The default set function for properties works on scalar objects only, but you can write your own functions (and any other function you overload or write yourself) to support vectors (or even matrices) of objects which you then act on.
Then your code above should work fine. I don't tend to do this myself except in a few places because it is a lot of effort supporting vectors of objects in all functions, but it can be useful.
You can do this, though it just moves the for loop inside the class:
classdef MyClass < handle
properties
Value
end
methods
function set.Value( objArray, value )
validateattributes( objArray, { 'MyClass' }, { 'vector' } )
validateattributes( value, { 'numeric' }, { 'scalar' } )
for i = 1:numel( objArray )
objArray(i).Value = value;
end
end
end
end
m(4) = MyClass;
m.Value = 7;
It quickly gets messy from a design perspective though because then you start asking yourself 'Should I also support a vector of values so that I can set the value of 10 objects to each value of an array of 10 numbers?'. And the code soon starts to get very complicated.
The plus operator could be similarly overloaded:
function objArray = plus( objArray, value )
validateattributes( objArray, { 'MyClass' }, { 'vector' } )
validateattributes( value, { 'numeric' }, { 'scalar' } )
for i = 1:numel( objArray )
objArray(i).Value = objArray(i).Value + value;
end
end
or something similar. Again though you have the questions of what you support because the standard + operator supports more than just adding a scalar to an array (as well as being symmetric, but that is another matter entirely).
Section 17-45 of the Matlab OOP bible covers other ways to overload the plus operator with a double operator overload also, but the class needs to be basically a wrapper for one main value property for this to make much sense. Just adding 7 to an arbitrary class full of properties doesn't really have an obvious meaning.
Even the simple early example in 2-6 to 2-7 of that linked document shows how quickly design question can start to arise from relatively simple overloads. In that example a plus operator is overloaded that simply adds the 'Value' or one class to the 'Value' of another. That is fair enough, but the output is a double. Personally I would expect that if I added two of those 'BasicClass' objects together I would end up with a BasicClass object as my output, containing the summed values of the two inputs, rather than just a raw double.
  댓글 수: 2
Stephen23
Stephen23 2017년 5월 12일
Note that set and get for graphics objects supports multiple handles and/or multiple values in arrays. As Adam says the syntax gets a bit complex, but it can be done.
Bryan Krause
Bryan Krause 2023년 10월 11일
It doesn't appear this approach works, or at least it doesn't work in more recent versions; an error "Assigning to (n) elements using a simple assignment statement is not supported." is thrown before the set.(PropertyName) method is called.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Data Type Identification에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by