Selecting data from a dynamically named ND array

1 次查看(过去 30 天)
I have a structure with fields of various dimensions - typically between 3 and 6. Each of the fields has one dimension that represents a sampling instance, but in some fields it is dimension 2, in others dimension 3 or 4. I need to extract a subset of the data from each of the fields by selecting samples along the relevant dimension, so if all of the fields were, say, 4D and the sampling dimension was 2 with ix as the selection, I could use:
flds = fieldnames(S.(inst))
for i = 1:numel(flds)
fld = flds{i};
S.(inst).(fld) = S.(inst).(fld)(:,ix,:,:);
clear fld
end; clear i
I can easily check the number of dimensions of the field and I can work out which dimension of the field I need to sample along, but I then end up with something like:
flds = fieldnames(S.(inst))
for i = 1:numel(flds)
fld = flds{i};
ndims = numel(size(S.(inst).(fld));
idir = find(size(S.(inst).(fld)) == Nsamples); % where Nsamples is the number of samples
if ndims == 3
if idir == 1
S.(inst).(fld) = S.(inst).(fld)(ix,:,:);
elseif idir == 2
S.(inst).(fld) = S.(inst).(fld)(:,ix,:);
else
S.(inst).(fld) = S.(inst).(fld)(:,:,ix;
end
elseif ndims == 4
if idir == 1
S.(inst).(fld) = S.(inst).(fld)(ix,:,:,:)
elseif idir == 2
% etc
% etc
end
clear fld
end; clear i
I wondered whether anyone could suggest a more elegant solution? I was thinking that it would be possible to dynamically generate the data selection (:,ix,:,:) as a text string and use it with eval, but I'm not sure that works with the dynamic naming of variables.
Any thoughts?

采纳的回答

Stephen23
Stephen23 2017-5-18
编辑:Stephen23 2018-11-6
For a start you might like to read this (if you want to write better code, then it can help you):
And then to solve your problem you do not need to write lots of if-s or use eval, in fact you can do solve your quite simply by creating a cell array of indices and using that to generate a comma-separated list:
>> X = randi(9,1,2,3,4);
>> C = {':',':',2,':'};
>> X(C{:})
ans(:,:,1,1) =
1 1
ans(:,:,1,2) =
8 2
ans(:,:,1,3) =
3 8
ans(:,:,1,4) =
2 4
Another alternative is to call subsref directly. The function subsref is what MATLAB uses to index into variables, but you can also call it directly. All you need to do is create a suitable structure input, it is not that hard but you should play around with it to understand how it works. For example:
>> subsref(X,substruct('()',C))
ans(:,:,1,1) =
1 1
ans(:,:,1,2) =
8 2
ans(:,:,1,3) =
3 8
ans(:,:,1,4) =
2 4
Clearly it is pretty trivial to construct that cell array: something like this (untested):
C = repmat({':'},1,totdim);
C{ixdim} = ix;
  2 个评论
Brian Scannell
Brian Scannell 2017-5-18
Ah, that looks ideal. I have found that there is nearly always a way to avoid using eval - your answer proves the point!
Many thanks, Brian
Stephen23
Stephen23 2017-5-18
@Brian: I am glad to help, and I hope that it works for you.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Logical 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by