table2stru​ct(struct2​table(s)) does not return s when some fields are cell arrays with a single element

7 views (last 30 days)
My actual goal is to sort a struct array by multiple fields. I have working code that looks roughly like this:
% We use stable sort calls in reverse priority order
[~, i_field3] = sort({my_struct.field3});
my_struct = my_struct(i_field3);
[~, i_field2] = sort([my_struct.field2]);
my_struct = my_struct(i_field2);
[~, i_field1] = sort([my_struct.field1]);
my_struct = my_struct(i_field1); % This is highest priority
I would like to follow the answer here, which vastly improves readability and maintainability:
T = struct2table(my_struct);
sortedT = sortrows(T, {'field1', 'field2', 'field3'});
my_struct = table2struct(sortedT);
However, the particular struct array I'm sorting has fields that are cell arrays, but often with a single element. Unfortunately, the new code doesn't preserve the cell array, and returns that single element only. A short way to reproduce/illustrate the problem would be this:
good_example = struct('field1', {{'abc', 'def'}}) % field1: {'abc' 'def'}
good_T = struct2table(good_example)
good_struct = table2struct(good_T) % field1: {'abc' 'def'}
bad_example = struct('field1', {{'abc'}}) % field1: {'abc'}
bad_T = struct2table(bad_example)
bad_struct = table2struct(bad_T) % field1: 'abc'
I want bad_struct to be identical to bad_example just like how good_struct is identical to good_example.
Obviously I could check for this situation and correct things, but that negates any readability/maintainability from using tables to do the sort.
Is there a way to guarantee that table2struct(struct2table(my_struct)) returns an identical struct array? Alternatively, is there a way to sort struct arrays that is better than my original code?

Accepted Answer

Stephen23
Stephen23 on 2 May 2023
"Is there a way to guarantee that table2struct(struct2table(my_struct)) returns an identical struct array?"
No.
"Alternatively, is there a way to sort struct arrays that is better than my original code?"
Perhaps a simple loop:
C = {'field1', 'field2', 'field3'};
X = 1:numel(S);
for k = numel(C):-1:1
[~,X] = sort({S.(C{k})});
S = S(X);
end
  1 Comment
Steve
Steve on 2 May 2023
OK. Glad I'm not missing anything built-in.
I like your simple loop. If I wrap that in a function it's even more readable than sortrows.
Thanks!

Sign in to comment.

More Answers (0)

Categories

Find more on Structures in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!