# Better way to pull out values from a struct

15 views (last 30 days)
Sam Litvin on 18 Jan 2020 at 5:13
Commented: Walter Roberson on 18 Jan 2020 at 8:33
I have a matrix with a matrix CT of struct data called callsTable. I'm trying to pull out just one of the columns called Time and create a 1D vector using the following code. Is there a better way that I can do this? Currently, running the code I get the following error message.
Unable to perform assignment because the size of the left side is 28-by-1 and the size of the right side is
6-by-1.
for k=1:size(CT,1)
for i=size(CT(k),1)
T(:,i)=CT(k).callsTable.Time
end
end

Walter Roberson on 18 Jan 2020 at 7:25
Times = arrayfun(@(S) S.callsTable.Time, CT, 'uniform', 0);
T = horzcat(Times{:});
The assignment to T will fail if the Time vectors were not all the same size.

Sam Litvin on 18 Jan 2020 at 7:43
Thanks Walter
I tried that, got this: Error using horzcat, Dimensions of arrays being concatenated are not consistent.
So then I tried vertcat instead, but got same issue as before. I am preallocatin the matrix by scanning the CT to find the max number there and creating a matrix of zeros
for n=1:size(CT,1)
call_tot=size(CT(n).callsTable.Time);
calls(n,:)=call_tot;
end
tablsize=size(CT,1);
maxcalls=max(calls);
T=zeros(maxcalls(1),tablsize);

Walter Roberson on 18 Jan 2020 at 7:59
time_lengths = arrayfun(@(S) length(S.callsTable.Time), CT);
max_time_lengths = max(time_lengths);
FirstN = @(V, N) V(1:N);
PadN = @(V, N) FirstN([V; zeros(N,1)]);
Times = arrayfun(@(S) PadN(S.callsTable.Time, max_time_lengths), CT, 'uniform', 0);
T = horzcat(Times{:});
Walter Roberson on 18 Jan 2020 at 8:29
time_lengths = arrayfun(@(S) length(S.callsTable.Time), CT);
max_time_lengths = max(time_lengths);
FirstN = @(V, N) V(1:N);
PadN = @(V, N) FirstN([V; zeros(N,1)], N);
Times = arrayfun(@(S) PadN(S.callsTable.Time, max_time_lengths), CT, 'uniform', 0);
T = horzcat(Times{:});

Sam Litvin on 18 Jan 2020 at 8:16
Thanks Walter, I really appreciate it.
Interesting method, I like it. Could you please explain what you're doing here:
FirstN = @(V, N) V(1:N);
PadN = @(V, N) FirstN([V; zeros(N,1)]);
because I get this error and I'm not sure how to debug
Not enough input arguments.
Error in Euler_GLM>@(V,N)V(1:N) (line 20)
FirstN = @(V, N) V(1:N)
Error in Euler_GLM>@(V,N)FirstN([V;zeros(N,1)]) (line 21)
PadN = @(V, N) FirstN([V; zeros(N,1)]);
Times = arrayfun(@(S) PadN(S.callsTable.Time, max_time_lengths), CT, 'uniform', 0);

#### 1 Comment

Walter Roberson on 18 Jan 2020 at 8:33
FirstN: takes the first N elements of whatever is handed in
PadN : take whatever input is given and always add N zeros at the end of it, and then call FirstN to pull out the first N of whatever that ends up being
So for example, PadN([1;2;3], 7) would form [1;2;3;0;0;0;0;0;0;0] and then ask FirstN to take the first 7 of those, getting out [1;2;3;0;0;0;0] as the result.
There are other ways of constructing something like this, including
PadN = @(V, N) [V; zeros(N-length(V), 1)]
which does not require as many steps.