doing operations on 1xN struct

4 次查看(过去 30 天)
Roei Shapira
Roei Shapira 2024-9-30
回答: Voss 2024-9-30
i have a structure that holds some data,
the structure is an array of structures (size of 1xN, N is an integer)
one of the data each struct holds is a 3 by 3 matrics with xyz positions of 3 points in space.
so a 1x2 structure will hold 2 matrics 3x3.
i need the square root of each row, but i dont know how to do it without a loop.
is there a way to get the square root of each row, within all the structures in the array without a loop?

回答(1 个)

Voss
Voss 2024-9-30
Constructing a structure array:
N = 2;
S = struct('matrix_field',permute(num2cell(rand(3,3,N),[1 2]),[1 3 2]),'other_field',{'something','else'})
S = 1x2 struct array with fields:
matrix_field other_field
S(1)
ans = struct with fields:
matrix_field: [3x3 double] other_field: 'something'
S(2)
ans = struct with fields:
matrix_field: [3x3 double] other_field: 'else'
If it's convenient for subsequent operations you need to do, you can concatenate all N 3x3 matrices into a 3x3xN array and take the square root of that, resulting in another 3x3xN array:
M = sqrt(cat(3,S.matrix_field));
disp(M)
(:,:,1) = 0.7156 0.3034 0.9401 0.8949 0.9009 0.7890 0.2553 0.7022 0.2558 (:,:,2) = 0.5955 0.3100 0.4549 0.9599 0.8806 0.8985 0.4852 0.8184 0.8393
Otherwise, you can use arrayfun, which is a loop, and which results in a cell array of 3x3 matrices:
C = arrayfun(@(s)sqrt(s.matrix_field),S,'UniformOutput',false)
C = 1x2 cell array
{3x3 double} {3x3 double}
celldisp(C)
C{1} = 0.7156 0.3034 0.9401 0.8949 0.9009 0.7890 0.2553 0.7022 0.2558 C{2} = 0.5955 0.3100 0.4549 0.9599 0.8806 0.8985 0.4852 0.8184 0.8393
Since that gives you a cell array, it's convenient to put the result in a new field in the original structure array, if that's ultimately what you want:
[S.sqrt_matrix_field] = C{:}
S = 1x2 struct array with fields:
matrix_field other_field sqrt_matrix_field
S(1).sqrt_matrix_field
ans = 3×3
0.7156 0.3034 0.9401 0.8949 0.9009 0.7890 0.2553 0.7022 0.2558
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
S(2).sqrt_matrix_field
ans = 3×3
0.5955 0.3100 0.4549 0.9599 0.8806 0.8985 0.4852 0.8184 0.8393
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Both of those approaches take the square root of each element of each matrix. Since you mentioned taking the square root of each row of each matrix, I'll make a guess at what that means (squaring each element, summing across each row, and taking the square root of that), and show it using both approches.
First the concatenation approach:
M = sqrt(sum(cat(3,S.matrix_field).^2,2));
disp(M)
(:,:,1) = 1.0256 1.2990 0.5017 (:,:,2) = 0.4217 1.4498 1.0001
It may be convenient to permute that 3x1xN array into a 3xN matrix:
M = permute(M,[1 3 2])
M = 3×2
1.0256 0.4217 1.2990 1.4498 0.5017 1.0001
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
And the arrayfun approach:
C = arrayfun(@(s)sqrt(sum(s.matrix_field.^2,2)),S,'UniformOutput',false)
C = 1x2 cell array
{3x1 double} {3x1 double}
celldisp(C)
C{1} = 1.0256 1.2990 0.5017 C{2} = 0.4217 1.4498 1.0001
And putting those results into the original structure array:
[S.sqrt_matrix_field] = C{:}
S = 1x2 struct array with fields:
matrix_field other_field sqrt_matrix_field
S(1).sqrt_matrix_field
ans = 3×1
1.0256 1.2990 0.5017
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
S(2).sqrt_matrix_field
ans = 3×1
0.4217 1.4498 1.0001
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
You could also concatenate the contents of each cell of C together to form a 3xN matrix:
M = [C{:}]
M = 3×2
1.0256 0.4217 1.2990 1.4498 0.5017 1.0001
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
but if that's the form of the result you need, it's better to skip the cell array entirely and use the concatenation approach.

产品


版本

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by