Display a struct as a table

255 vues (au cours des 30 derniers jours)
Yang
Yang le 5 Fév 2016
Hi all,
I have a struct. I want to display the content of this struct as a table. So I use the following transformation.
aTable = struct2table(aStruct);
disp(aTable);
We can see the value of modifiedTime is not correct. I hope to display it as a value, not as an array. Can you tell me how I can do it?
Thanks.
aStruct =
LocalName: {'example.cdf'}
Size: '1 KB'
ModifiedTime: '10-May-2010 21:35:00'
LocalName Size ModifiedTime
_____________ ____ ____________
'example.cdf' 1 KB [1x20 char]
  1 commentaire
Matthew Eicholtz
Matthew Eicholtz le 5 Fév 2016
I'm not sure why the display ends up looking like that, but for what it's worth, it displayed ModifiedTime correctly when I added additional entries (e.g. S(2).LocalName = 'test',...).

Connectez-vous pour commenter.

Réponse acceptée

Steve Eddins
Steve Eddins le 5 Fév 2016
Convert the string containing the date and time into a datetime value, and then it will display better in the table.
aStruct.LocalName = {'example.cdf'};
aStruct.Size = '1 KB';
aStruct.ModifiedTime = '10-May-2010 21:35:00';
aTable = struct2table(aStruct);
aTable.ModifiedTime = datetime(aTable.ModifiedTime)
aTable =
LocalName Size ModifiedTime
_____________ ____ ____________________
'example.cdf' 1 KB 10-May-2010 21:35:00
  2 commentaires
Peter Perkins
Peter Perkins le 30 Avr 2018
Steve's answer certainly solves this problem.
But the real issue lies deeper. Let's say that the structure's third field was named ModifiedCity, and its value was 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch' (google it):
>> aStruct.LocalName = {'example.cdf'};
>> aStruct.Size = '1 KB';
>> aStruct.ModifiedCity = 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch';
>> aTable = struct2table(aStruct)
aTable =
1×3 table
LocalName Size ModifiedCity
_____________ ____ ____________
'example.cdf' 1 KB [1x58 char]
What's going on is a mix of raw data types and containers and sizes that seems like it ought to be simple but for various reasons has complications. The explanation takes some digging into data types, issues that have been addressed with the new-ish (in R2016b) string data type.
So what's the short answer? Either set struct2table's 'AsArray' parameter to true, or, in recent versions of MATLAB, store those text values as strings:
>> anotherStruct.LocalName = "example.cdf";
>> anotherStruct.Size = "1 KB";
>> anotherStruct.ModifiedCity = "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch";
>> anotherTable = struct2table(anotherStruct)
anotherTable =
1×3 table
LocalName Size ModifiedCity
_____________ ______ ____________________________________________________________
"example.cdf" "1 KB" "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch"
The longer answer: aStruct is a scalar struct. So without having anything else to go on, struct2table treats each of its fields as a variable in the resulting table. That's the most common case for calling struct2table on a scalar struct. Each field is 1-by-something, so the resulting table is 1x3. Each of its variables is exactly the corresponding field from the struct. LocalName is a 1x1 cell array that contains a char row, size is a 1x3 char, and ModifiedCity is a 1x58 char.
table's display limits the width it will show for a variable that's a char to 10 chars. More than than, and you get a summary of the type and size. table display is not intended for "pretty printing", and a char matrix is a really old way to store text data. Notice that I said "char matrix". There's the complicated detail. Back to that in a moment.
OTOH, table display is willing to show the full width of a string or cellstr ("cell array of char row vectors") variable. So you might think to put {'example.cdf'} in aStruct.LocalName, and that would work. But it would be kind of an unusual thing to do (I assume the OP did that just to illustrate part of his confusion). More typical would be to store 'example.cdf' (the reason is that the fields of a struct are very much like the cells of a cell array -- aStruct.LocalName gets the "contents of" that field in the same way that aCell{1} would). In any case, as we'll see, it turns out the same.
Back to char arrays.
If the struct had two elements, with field values similar to the scalar version, struct2table would have said to itself, "each element of this non-scalar struct should become a row of the table. And when people store char row vectors in fields of a non-scalar struct, the best way to combine them is to create a cellstr":
>> aStruct2 = [aStruct; aStruct]
aStruct2 =
2×1 struct array with fields:
LocalName
Size
ModifiedCity
>> aTable = struct2table(aStruct2)
aTable =
2×3 table
LocalName Size ModifiedCity
_____________ ______ ____________________________________________________________
'example.cdf' '1 KB' 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'
'example.cdf' '1 KB' 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'
All three of the variables in that 2x3 table are cellstrs.
So the trick is to tell struct2table that you want to treat that scalar struct as one row of a 1x3 table, and not treat each field of aStruct as a variable in the table. It will do either, but most of the time, calling struct2table on a scalar struct is intended to do the latter. So there's 'AsArray' to do the former:
>> aTable = struct2table(aStruct,'AsArray',true)
aTable =
1×3 table
LocalName Size ModifiedCity
_____________ ______ ____________________________________________________________
'example.cdf' '1 KB' 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'
This may seem arcane. In effect it's an artifact of using a data type that's mostly about manipulating data, as a tool for "pretty printing". It works sometimes, sometimes you need to do special things to get it to look right.
In any case, in new code, using string is a great idea for many reasons, and removes all the complication from char vs. cellstr.
Alexander Hallberg
Alexander Hallberg le 3 Mai 2022
Thank you Steve!

Connectez-vous pour commenter.

Plus de réponses (1)

Andrei
Andrei le 30 Avr 2018
Using struct2table with the 'AsArray' true option produces the desired behavior:
T = struct2table(S, 'AsArray', true);

Catégories

En savoir plus sur Data Type Conversion dans Help Center et File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by