I would like to know if there exists a way in MATLAB to create a dictionary like in Python.
I have several Port Name and Port Type and I would like to create a dictionary like this :
dict = {PortName : PortType, PortName : PortType, ...}
I would like to know if there exists a way in MATLAB to create a dictionary like in Python.
I have several Port Name and Port Type and I would like to create a dictionary like this :
dict = {PortName : PortType, PortName : PortType, ...}
EDIT: Since R2022b Matlab has a dictionary
type, which is recommended over containers.Map
.
The closest analogy is containers.Map
:
containers.Map
: Object that maps values to unique keys
The keys are character vectors, strings, or numbers. The values can have arbitrary types.
To create the map you pass containers.Map
a cell array of keys and a cell array of values (there are other, optional input arguments):
>> dict = containers.Map({ 'a' 'bb' 'ccc' }, { [1 2 3 4], 'Hey', {2 3; 4 5} });
>> dict('a')
ans =
1 2 3 4
>> dict('bb')
ans =
'Hey'
>> dict('ccc')
ans =
2×2 cell array
{[2]} {[3]}
{[4]} {[5]}
You can also append key-value pairs to an existing map:
>> dict('dddd') = eye(3);
>> dict('dddd')
ans =
1 0 0
0 1 0
0 0 1
However, depending on what you want to do there are probably more Matlab-like ways to do it. Maps are not so widely used in Matlab as dictionaries are in Python.
You can use containers.Map
as suggested by Luis Mendo in the other answer, but I think in this case a struct
is much simpler:
>> dict = struct('a',[1 2 3 4], 'bb','Hey', 'ccc',{2 3; 4 5});
>> dict.('a')
ans =
1 2 3 4
>> dict.a
ans =
1 2 3 4
>> dict.b
ans =
'Hey'
>> dict.ccc
ans =
2×2 cell array
{[2]} {[3]}
{[4]} {[5]}
>> dict.dddd = eye(3);
>> dict.('eee') = eye(3);
>> dict.dddd
ans =
1 0 0
0 1 0
0 0 1
That is, the struct is always indexed using .('name')
or simply .name
. But there are restrictions on what 'name' can be (it must be a valid variable name), unlike for the Map
.
See this other answer to learn about important differences between the two approaches.
MATLAB R2022b has a new dictionary
datatype that is significantly better than containers.Map
. A tutorial describing it can be found on The MATLAB blog https://blogs.mathworks.com/matlab/2022/09/15/an-introduction-to-dictionaries-associative-arrays-in-matlab/
For example:
names = ["Mike","Dave","Bob"];
weights = [89,75,68]; % weight in kilograms
gym = dictionary(names,weights) % Vectorised constructor. Performs elementwise mapping.
gives
gym =
dictionary (string ⟼ double) with 3 entries:
"Mike" ⟼ 89
"Dave" ⟼ 75
"Bob" ⟼ 68
I wrote a func to make containers.Map
via dict(a=1, b='yes')
syntax. Dunno if foulproof but seems to work, also wrote a function to pretty print a containers.Map
. Demo:
d = dict(a=1, mode='fast', arr=[[1 2 3]; [5 6 7]], yes=dict(k=2));
disp(dict2str(d))
a=1, arr=[1 2 3] [5 6 7], mode='fast', yes=dict(k=2,),
also guards against very long prints but this can be improved:
d = dict(a=randn(1000));
disp(dict2str(d))
a=<double>,
function out = dict(varargin)
% DICT Python dictionary syntax
%
% out = dict(a=1, mode='fast', arr=[1 2 3], yes=dict(k=2))
%
% Show with
%
% disp(dict2str(out))
out = containers.Map('UniformValues', false);
current_key = '';
for i=1:length(varargin)
if mod(i, 2)
current_key = varargin{i};
else
out(current_key) = varargin{i};
end
end
end
function out = dict2str(d, C)
% DICT2STR
%
% `disp(out)` is like
% analytic=true, normalize='l1', paths_exclude=None, r_psi=.70711
arguments
d;
C.delim = ', ';
C.max_value_length = 50;
end
keys = d.keys;
values = d.values;
out = "";
for i=1:length(keys)
k = keys{i};
v = values{i};
if class(v) == "containers.Map"
vs = "dict(" + dict2str(v) + ")";
elseif isnumeric(v) && length(v) > 1
vs = "[" + join(string(v)) + "]";
elseif isempty(v)
vs = "None";
elseif ismember(class(v), ["string", "char"])
vs = sprintf("'%s'", join(string(v)));
else
vs = join(string(v));
end
if C.max_value_length && length(vs) > C.max_value_length
vs = "<" + class(v) + ">";
end
out = out + sprintf("%s=%s%s", join(string(k)), join(string(vs)), C.delim);
end
% strip delimiter
for i=1:length(C.delim)
out = strip(out, 'right', C.delim(i));
end
end