How do I use indexing (vectorization?) rather than for loops for dynamic field referencing into a cell array?
6 次查看(过去 30 天)
显示 更早的评论
I think there's a way to eliminate for loops by indexing, or perhaps it's called vectorizing. How do I do this?
For example, I'm trying to plot several vectors of different lengths in the same 3D scatter plot. This code stores 34 DICOM ROI items' double arrays in a 1x34 cell array:
info = dicominfo('filename.dcm');
numberofarrays = 34;
datacells = cell(1,numberofarrays);
names = fieldnames(info.ROIContourSequence.Item_9.ContourSequence);
for loop = 1:numberofarrays
datacells(loop) = {info.ROIContourSequence.Item_9.ContourSequence.(names{loop}).ContourData(:,1)};
end
but this code results in the following error:
datacellsfaster(1:34) = {info.ROIContourSequence.Item_9.ContourSequence.(names{1:34}).ContourData(:,1)};
Expected one output from a curly brace or dot indexing expression, but there were 34 results.
Why was it expecting only one output? How do I eliminate for loops through indexing?
0 个评论
采纳的回答
Guillaume
2016-6-10
I'm suprised you get Expected one output from a curly brace or dot indexing expression as an error and not Argument to dynamic structure reference must evaluate to a valid field name.
Unfortunately, you cannot pass a cell array as dynamic field names, The dynamic name must be a scalar string so,
.ContourSequence.(name{1:34})
is never going to work.
If all the ContourData have the same size you could eliminate the loop with struct2cell and by concatenating all the CountourData into one big matrix. There's no guarantee that it'd be faster, and it certainly would use up a lot more memory.
You're better off with the loop. In any case, with only 34 iterations that loop should execute very quickly.
4 个评论
Guillaume
2016-6-17
ismember, as a built-in function, is going to be faster than a loop. The bottleneck is going to be the accumarray calls due to the use of a non-standard accumulation function (the @(x) {x} anonymous function).
In my example, accumarray does not sum the resulting values, it extracts the series of coordinates exactly as you want. The accumulation function I've specified simply wrap the accumulated vectors (all the values that match a depth) into a cell array.
find is indeed often unnecessary and using logical indexing directly will speed up your code by a small amount indeed.
By the way, I forgot to say, another way to write your initial loop
for loop = 1:numberofarrays
datacells(loop) = {info.ROIContourSequence.Item_9.ContourSequence.(names{loop}).ContourData(:,1)};
end
would be, assuming that numberofarrays == numel(fieldnames(info.ROIContourSequence.Item_9.ContourSequence)):
datacells = structfun(@(seq) {seq.ContourData(:, 1)}, info.ROIContourSequence.Item_9.ContourSequence);
structfun iterates over all the fields of ContourSequence and, again, the anonymous function simply wrap the ContourData of each field into a cell array. I don't expect any significant gain in speed with that syntax, the looping may be faster but you now have the cost of a function call (to the anonymous function).
更多回答(1 个)
geotocho
2017-10-28
Rather than curly brace indexing, the vectorized way of assigning a command to all cells uses parentheses. Much like the traditional array but in this example A and B are cell arrays of the same size. I wish to assign the row of cells in A to B. In this manner dot indexing is allowed.
B(1,:) = A(1,:);
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Loops and Conditional Statements 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!