Deleting specific values of fields inside a struct array

Hello everyone,
I have a struct array with multiple fields. All fields are arrays with the same length.
a=struct();
a.field1=rand(20,1);
a.field2=rand(20,1);
a.field3=rand(20,1);
Is there away to delet a specific element from all field arrays at the same time?
So for example delete element 3 from field1, field2 and field3 under specific conditions, for example when field3 value==0.5.
I just know this way:
a.field1(a.field3==0.5)=[];
a.field2(a.field3==0.5)=[];
a.field3(a.field3==0.5)=[];
But is it possible to do this in on line instead of handling every field seperatly?
Best regrads
Marc

1 件のコメント

Stephen23
Stephen23 2020 年 5 月 2 日
"But is it possible to do this in on line instead of handling every field seperatly?"
You could use a loop or structfun (which just hides the loop inside).
Note that comparing floating point numbers for exact equality is a common cause of bugs, you should probably compare the absolute difference against a tolerance:
idx = abs(A-B)<tol

サインインしてコメントする。

 採用された回答

Ameer Hamza
Ameer Hamza 2020 年 5 月 2 日
編集済み: Ameer Hamza 2020 年 5 月 2 日

1 投票

Something like this
a=struct();
a.field1=rand(20,1);
a.field2=rand(20,1);
a.field3=rand(20,1);
mask = a.field3==a.field3(5); % a.field3(5) is used as example
a = cell2struct(structfun(@(x) {x(~mask)}, a), fieldnames(a));
Result:
>> a
a =
struct with fields:
field1: [19×1 double]
field2: [19×1 double]
field3: [19×1 double]
An alternative way is to use the for-loop. It will probably be faster than the above code because it does not need to create a temporary cell array and recreate the struct.
mask = a.field3==a.field3(5);
names = fieldnames(a);
for i=1:numel(names)
a.(names{i})(mask) = [];
end
Note: If you are going to set the value for comparison with a.field3 arbitrarily, i.e., the comparison value is not already an element of the a.field3 itself. The comparison == for floating-point value can fail. In that case, you can define the mask based on tolerance.
mask = abs(a.field3 - 0.5) < 1e-6; % 1e-6 is the tolerance for the comparison with 0.5

5 件のコメント

Marc Laub
Marc Laub 2020 年 5 月 2 日
Yes something like this,
I used
a(1:somevalue)=struct();
before. So i could index the struct directly and delete the values from every field. But to allocate multiple values to the fields at one i had to use cell2mat and mat2cell. I wanted to bypass that by handling the fields itself as arrays. That leads me to the problem that i cant delete specific field elements without using cell2mat or cell2struct.
I thought there was a simpler way, without transforming between cells, mats and structs
Thank you for your help
Ameer Hamza
Ameer Hamza 2020 年 5 月 2 日
Check the second code in the updated answer.
Image Analyst
Image Analyst 2020 年 5 月 2 日
Sorry but that will only work for multiples of 2 or inverse multiples of 2 like 0.5. Why? Please refer to the FAQ: Why_is_0.3_-_0.2_-_0.1_or_similar_not_equal_to_zero?
Better show him how to use ismembertol(), because he'll soon come back to you saying it doesn't work again.
Ameer Hamza
Ameer Hamza 2020 年 5 月 2 日
Good point. I assumed that the comparison value would be taken out of the vector itself, e.g., using min(), max(), etc. But if some other operations are performed on the value, then the == comparison can fail.
Marc Laub
Marc Laub 2020 年 5 月 5 日
Its ok,
I modified it anyway to:
mask = a.field3==2;
since my trigger value isalways 2, so its fine.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeStructures についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by