Deleting Elements in a Structure - Error Matrix Index is Out of Range

1 visualizzazione (ultimi 30 giorni)
I have a struct with several fields
x.score = [98 75 22 75 29];
x.count = [1 2 3 4 5];
I want to delete all the elements in x (in all fields) that have a count < 4. So in this case I want X to be
x.score = [98 75 22]
x.count = [1 2 3]
Why doesn't this cmd work?
x([x.count<4]) = []
Matrix index is out of range for deletion.
  1 Commento
Stephen23
Stephen23 il 20 Ago 2022
Modificato: Stephen23 il 20 Ago 2022
"Why doesn't this cmd work?"
Because you are mixing up indexing into x (which is a scalar structure) with indexing into the fields of x (which are numeric vectors). If you want to remove elements from the fields of x then you need to index into those fields, and not by attempting to into the scalar structure x. Sometimes it is useful to index into a structure, but not if your goal is to index into its fields!
x.score = [98,75,22,75,29];
x.count = [1,2,3,4,5];
idx = x.count>=4;
x.score(idx) = [];
x.count(idx) = []
x = struct with fields:
score: [98 75 22] count: [1 2 3]
Note that these square brackets are completely superfluous, get rid of them: [x.count<4] Even if x was non-scalar that would still be invalid syntax, so they indicate (as most situations where a user has superfluous square brackets) a confusion about what square brackets do and when to use them:
y(1).count = 1;
y(2).count = 2;
[y.count<4] % square brackets don't do anything useful here either
Error using <
Too many input arguments.

Accedi per commentare.

Risposta accettata

Voss
Voss il 19 Ago 2022
Modificato: Voss il 22 Ago 2022
x.score = [98 75 22 75 29];
x.count = [1 2 3 4 5];
x.count<4 is a 1x5 logical array
x.count<4
ans = 1×5 logical array
1 1 1 0 0
x(x.count<4) = [] would try to delete elements 1, 2, 3 of x (where x.count<4 is true), but you can't do that because x only has one element
size(x)
ans = 1×2
1 1
so you get the error.
Instead of deleting elements of x, you want to delete elements of each field of x, which can be done as follows:
f = fieldnames(x);
idx_to_delete = x.count<4;
for ii = 1:numel(f)
x.(f{ii})(idx_to_delete) = [];
end
disp(x)
score: [75 29] count: [4 5]
This gives a result different than what you specified the result should be. Perhaps the condition should be x.count>=4?
x.score = [98 75 22 75 29]; % re-create x
x.count = [1 2 3 4 5];
f = fieldnames(x);
idx_to_delete = x.count>=4;
for ii = 1:numel(f)
x.(f{ii})(idx_to_delete) = [];
end
disp(x)
score: [98 75 22] count: [1 2 3]
  4 Commenti
John
John il 22 Ago 2022
Modificato: John il 22 Ago 2022
Thanks. I was expecting a way to filter on data with a large number of fields without having to write a loop. Maybe using a table instead of struct is more appropriate. I have a large number of fields that I want to filter on multiple parameters to looks for patterns in a subset of the data.
Voss
Voss il 22 Ago 2022
You're welcome! Yes, a table may be more convenient, or just use a loop.

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Structures in Help Center e File Exchange

Prodotti


Release

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by