Trouble using container with cell type for key and structure array for values..

Given this table,
TestTable_valid =
11×6 table
SerialNumber ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No
____________________ __________________ ___________________ __________ _________ _______________
{'A017441206210001'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2C' } {'Yes'}
{'A017441229220004'} {'7.0A'} {'8.6A'} {'Passed'} {'VA2C' } {'Yes'}
{'A020621202230003'} {'0A' } {'7.7A'} {'Failed'} {'VA2CE'} {'Yes'}
{'A020621203230003'} {'0A' } {'7.6A'} {'Failed'} {'VA2CE'} {'Yes'}
{'A020621207230002'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'}
{'A020621208230001'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'}
{'A020621210230006'} {'1.2A'} {'0.7' } {'Failed'} {'VA2CE'} {'Yes'}
{'A020621215230003'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'}
{'A020621222230004'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'}
{'A020622108240013'} {'7.1A'} {'0A' } {'Passed'} {'VA2CE'} {'Yes'}
{'A020622109240009'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2CE'} {'Yes'}
I'm trying to create a container that uses the serial number as the key, and returns the other columns:
serials = TestTable_valid.SerialNumber
dataValues = TestTable_valid(:, 2:6)
dataStructArray = table2struct(dataValues)
% Create map: key = serial number, value = table row with C–G
lookupMap = containers.Map(serials, dataStructArray, 'UniformValues', false); % needed because data types in structure may be different.
however, I get the following error:
Error using containers.Map
Specified value type does not match the type expected for this container.
Don't know what else to try...I'm not sure cell vs. character array, vs cell array of characters, so perhaps that is the issue.....
I appreciate the help...
Jorge

6 Commenti

Given this table,...
Are we? I see no .mat attachment.
It is not clear that containers.Map supports struct arrays for valueset
Adding a runnable example.
TestTable_valid = readtable('TestTable_valid.xlsx')
TestTable_valid = 11x6 table
SerialNumber ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No ____________________ __________________ ___________________ __________ _________ _______________ {'A017441206210001'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2C' } {'Yes'} {'A017441229220004'} {'7.0A'} {'8.6A'} {'Passed'} {'VA2C' } {'Yes'} {'A020621202230003'} {'0A' } {'7.7A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621203230003'} {'0A' } {'7.6A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621207230002'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621208230001'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621210230006'} {'1.2A'} {'0.7' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621215230003'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621222230004'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020622108240013'} {'7.1A'} {'0A' } {'Passed'} {'VA2CE'} {'Yes'} {'A020622109240009'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2CE'} {'Yes'}
serials = TestTable_valid.SerialNumber
serials = 11x1 cell array
{'A017441206210001'} {'A017441229220004'} {'A020621202230003'} {'A020621203230003'} {'A020621207230002'} {'A020621208230001'} {'A020621210230006'} {'A020621215230003'} {'A020621222230004'} {'A020622108240013'} {'A020622109240009'}
dataValues = TestTable_valid(:, 2:6)
dataValues = 11x5 table
ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No __________________ ___________________ __________ _________ _______________ {'7.1A'} {'7.1A'} {'Passed'} {'VA2C' } {'Yes'} {'7.0A'} {'8.6A'} {'Passed'} {'VA2C' } {'Yes'} {'0A' } {'7.7A'} {'Failed'} {'VA2CE'} {'Yes'} {'0A' } {'7.6A'} {'Failed'} {'VA2CE'} {'Yes'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'1.2A'} {'0.7' } {'Failed'} {'VA2CE'} {'Yes'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'7.1A'} {'0A' } {'Passed'} {'VA2CE'} {'Yes'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2CE'} {'Yes'}
dataStructArray = table2struct(dataValues)
dataStructArray = 11x1 struct array with fields:
ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No
% Create map: key = serial number, value = table row with C–G
lookupMap = containers.Map(serials, dataStructArray, 'UniformValues', false); % needed because data types in structure may be different.
Error using containers.Map
Specified value type does not match the type expected for this container.
@Cris LaPierre, thanks for creating the table so that it can be imported and run with the code provided. Now I know to do this in the future!
If i don't convert the dataValues to a structure, then I get this other error:
Error using containers.Map
The number of keys and values must be the same.
So, all I want to be able to do is to use the SN (which comes from a different source) as a lookup into this table and extract the other fields. I guess I can do a row by row string compare and use the index of the matching row to extract the field values from the table...but I thought this would be the more elegant way....
As of R2025a (currently pre-release), you will be able to use
dataStructArray = num2cell(dataValues,2);
to create a cell array in which each row is a cell array containing the variables.
Unfortunately in R2024b and earlier, building such a cell array is most easily done using a loop.
this worked....
TestTable_valid = readtable('TestTable_valid.xlsx')
TestTable_valid = 11x6 table
SerialNumber ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No ____________________ __________________ ___________________ __________ _________ _______________ {'A017441206210001'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2C' } {'Yes'} {'A017441229220004'} {'7.0A'} {'8.6A'} {'Passed'} {'VA2C' } {'Yes'} {'A020621202230003'} {'0A' } {'7.7A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621203230003'} {'0A' } {'7.6A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621207230002'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621208230001'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621210230006'} {'1.2A'} {'0.7' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621215230003'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621222230004'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020622108240013'} {'7.1A'} {'0A' } {'Passed'} {'VA2CE'} {'Yes'} {'A020622109240009'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2CE'} {'Yes'}
serials = cell(TestTable_valid.SerialNumber)
serials = 11x1 cell array
{'A017441206210001'} {'A017441229220004'} {'A020621202230003'} {'A020621203230003'} {'A020621207230002'} {'A020621208230001'} {'A020621210230006'} {'A020621215230003'} {'A020621222230004'} {'A020622108240013'} {'A020622109240009'}
dataCell = table2cell(TestTable_valid(:, 2:6));
rowCells = mat2cell(dataCell, ones(size(dataCell,1),1),size(dataCell,2))
rowCells = 11x1 cell array
{1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell} {1x5 cell}
lookupMap = containers.Map(serials, rowCells)
lookupMap =
Map with properties: Count: 11 KeyType: char ValueType: any
fields = lookupMap(serials{1})
fields = 1x5 cell array
{'7.1A'} {'7.1A'} {'Passed'} {'VA2C'} {'Yes'}
fprintf('SN: %s | Pre: %s | Post: %s | Result: %s | Model: %s | LCR: %s\n', ...
serials{1}, fields{1}, fields{2}, fields{3}, fields{4}, fields
SN: A017441206210001 | Pre: 7.1A | Post: 7.1A | Result: Passed | Model: VA2C | LCR: Yes
Thank you for your help.

Accedi per commentare.

 Risposta accettata

struct values are not permitted.
keys = 100:110;
values = struct('abc', num2cell(1:11))
values = 1x11 struct array with fields:
abc
containers.Map(keys, values)
Error using containers.Map
Specified value type does not match the type expected for this container.

Più risposte (2)

Perhaps use a dictionary, instead of containers.Map?
keys = compose("A0%.2d" , 1:15);
values = struct('abc', num2cell(1:15));
d=dictionary(keys, values),
d = dictionary (string --> struct) with 15 entries: "A001" --> 1x1 struct "A002" --> 1x1 struct "A003" --> 1x1 struct "A004" --> 1x1 struct "A005" --> 1x1 struct "A006" --> 1x1 struct "A007" --> 1x1 struct "A008" --> 1x1 struct "A009" --> 1x1 struct "A010" --> 1x1 struct "A011" --> 1x1 struct "A012" --> 1x1 struct "A013" --> 1x1 struct "A014" --> 1x1 struct "A015" --> 1x1 struct
d("A008")
ans = struct with fields:
abc: 8
Is there a reason you want to use a container other than table?
Are the SerialNumbers unique? If so, you can put them in the RowNames property of the table and "query" the table using subscripting:
TestTable_valid = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1833727/TestTable_valid.xlsx')
TestTable_valid = 11×6 table
SerialNumber ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No ____________________ __________________ ___________________ __________ _________ _______________ {'A017441206210001'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2C' } {'Yes'} {'A017441229220004'} {'7.0A'} {'8.6A'} {'Passed'} {'VA2C' } {'Yes'} {'A020621202230003'} {'0A' } {'7.7A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621203230003'} {'0A' } {'7.6A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621207230002'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621208230001'} {'0A' } {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'} {'A020621210230006'} {'1.2A'} {'0.7' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621215230003'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020621222230004'} {'0A' } {'0A' } {'Failed'} {'VA2CE'} {'Yes'} {'A020622108240013'} {'7.1A'} {'0A' } {'Passed'} {'VA2CE'} {'Yes'} {'A020622109240009'} {'7.1A'} {'7.1A'} {'Passed'} {'VA2CE'} {'Yes'}
TestTable_valid.Properties.RowNames = TestTable_valid.SerialNumber;
TestTable_valid.SerialNumber = [];
TestTable_valid.Properties.DimensionNames(1) = "SerialNumber";
% get all data for one row
TestTable_valid("A020621208230001",:)
ans = 1×5 table
ACCurrentPreSyncEn ACCurrentPostSyncEn PassFail Model LCRSwept_Yes_No __________________ ___________________ __________ _________ _______________ A020621208230001 {'0A'} {'7.1A'} {'Failed'} {'VA2CE'} {'Yes'}
% get just PassFail for one row
TestTable_valid.PassFail("A020621208230001")
ans = 1×1 cell array
{'Failed'}
% and of course, table, unlike dictionary, means that if you need to slice
% across all SerialNumbers, you still can:
TestTable_valid.Model
ans = 11×1 cell array
{'VA2C' } {'VA2C' } {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'} {'VA2CE'}

4 Commenti

Is there a reason you want to use a container other than table?
Perhaps because tables are slow?
TestTable_valid = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1833727/TestTable_valid.xlsx');
TestTable_valid.Properties.RowNames = TestTable_valid.SerialNumber;
TestTable_valid.SerialNumber = [];
TestTable_valid.Properties.DimensionNames(1) = "SerialNumber";
start = tic;
TestTable_valid("A020621208230001",:);
TestTable_valid("A017441206210001",:);
TestTable_valid("A020622109240009",:);
t1 = toc(start)
t1 = 0.0223
rownames = TestTable_valid.Properties.RowNames;
as_cell = arrayfun(@(IDX) {TestTable_valid{IDX,2:end}}, 1:height(TestTable_valid)).';
C = containers.Map(rownames, as_cell);
start = tic;
C("A020621208230001");
C("A017441206210001");
C("A020622109240009");
t2 = toc(start)
t2 = 0.0020
D = dictionary(rownames, as_cell);
start = tic;
D({'A020621208230001'});
D({'A017441206210001'});
D({'A020622109240009'});
t3 = toc(start)
t3 = 0.0020
Thank you @Walter Roberson:
no....just not knowledgeable enough.....primary intent was to be able to enable the look up of an entry on a table from the key (the serial number) provided from another table of collected data. Which is the "better" way to do it?
@Walter Roberson, Perhaps. That's why I asked the question. You and Matt are correct that if you just need to access data by looking up the SerialNumber, the fastest thing is to use a dictionary. (And we encourage you to use dictionary rather than containers.Map. Dictionary addresses several performance and behavioral issues with containers.). Lookup performance can be particularly important when doing a fast calculation in a tight loop and dictionary probably wins there. However, as I attempted to illustrate above, if Jorge wants to do things other than look up rows, then table may still be a good option. Vectorized calculations on one variable are a lot faster and easier on the table than the dictionary of structs.
Having real-world use cases is helpful for me as I think about table performance, because there are ultimately trade-offs in performance and functionality.

Accedi per commentare.

Prodotti

Release

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by