1

In Python:

my_list = []
my_dict_a = {1: 'one'}
my_dict_b = {2: 'two'}
my_dict_c = {3: 'three'}
my_list.append(my_dict_a)
my_list.append(my_dict_b)
my_list.append(my_dict_c)

Where my_list will now equal [{1: 'one'}, {2: 'two'}, {3: 'three'}].

If we can say that a containers.Map is the basic equivalent of a python dict, what is the MATLAB equivalent to the above python append?

What I have tried in MATLAB:

Knowing:

>a=[];
>b=1;    
>a = [a, b]

a =  1

>a = [a, b]

a = 1     1

>a = [a, b]

a = 1     1     1

and

>a={};
>b=1;
>a=[a,b]

a = [1]

>a=[a,b]

a = [1]    [1]

>a=[a,b]

a = [1]    [1]    [1]

and

>a = [a; b]

a = 1

>a = [a; b]

a = 1
    1

>a = [a; b]

a =
     1
     1
     1

and yet when I try to do the same to a containers.Map object:

>dictA=containers.Map();
>dictA('first')=1;
>dictA('second')=2;
>dictA('third')=3;

>a=[];
>a = [a, dictA]

a = 

  Map with properties:

        Count: 3
      KeyType: char
    ValueType: any

>a = [a, dictA]
Error using containers.Map/horzcat
Horizontal concatenation is not supported by a containers.Map.

ok. but what about:

>a=[];
>a = [a; dictA]

a = 

  Map with properties:

        Count: 3
      KeyType: char
    ValueType: any

>a = [a; dictA]

a = 

  Map with properties:

        Count: 3
      KeyType: char
    ValueType: any

>whos a
  Name      Size            Bytes  Class             Attributes

  a         3x1               112  containers.Map

and yet it didnt keep appending:

>a={};
>a = [a; dictA]

a = 

  Map with properties:

        Count: 3
      KeyType: char
    ValueType: any

>a = [a; dictA]

a = 

  Map with properties:

        Count: 3
      KeyType: char
    ValueType: any

>whos a
  Name      Size            Bytes  Class             Attributes

  a         3x1               112  containers.Map     

and yet

>{dictA}

ans = 

    [3x1 containers.Map]


>a = {};
>a = [{a}; {dictA}]

a = 

    {}
    [3x1 containers.Map]

>a = [{a}; {dictA}]

a = 

    {2x1 cell          }
    [3x1 containers.Map]

>whos a
  Name      Size            Bytes  Class    Attributes

  a         2x1               672  cell               

>a = [{a}; {dictA}]

a = 

    {2x1 cell          }
    [3x1 containers.Map]

>whos a
  Name      Size            Bytes  Class    Attributes

  a         2x1              1008  cell       

>a = {};
>a = {a dictA}

a = 

    {}    [3x1 containers.Map]

>whos a
  Name      Size            Bytes  Class    Attributes

  a         1x2               336  cell               

a = {a dictA}

a = 

    {1x2 cell}    [3x1 containers.Map]

>whos a
  Name      Size            Bytes  Class    Attributes

  a         1x2               672  cell 

and lastly

>a = {};
>a = {[a] [dictA]}

a = 

    {}    [3x1 containers.Map]

>a = {[a] [dictA]}

a = 

    {1x2 cell}    [3x1 containers.Map]

>a = {[a] [dictA]}

a = 

    {1x2 cell}    [3x1 containers.Map]
Aaron
  • 132
  • 2
  • 3
  • 17
  • 1
    [Structures](http://www.mathworks.com/help/matlab/structures.html), probably. – sco1 Feb 16 '16 at 21:32
  • @excaza Thank you. However, I am trying to ask about a ```container.Map```, which seems to be the parallel to a python dict, and I am trying to discover how to create a list, e.g. ```cell array``` of ```map containers```. Unless, a structure is in fact a closer parallel to a python dict? – Aaron Feb 16 '16 at 22:47

2 Answers2

2

The containers.Map class does not support the same kind of array concatenation that you can do with numerical arrays (in part because the Map class overloads some of the array access functions). So you cannot make an array of Map objects (despite the lack of an error message when you tried vertical concatenation).

Cell array of containers.Map objects

However, you can make a cell array of Map objects; you just need to be careful about the syntax. You got pretty close, but I think this is what you want:

>> a = {};
>> a = [a, {dictA}]
a = 
    [3x1 containers.Map]

>> a = [a, {dictA}]
a = 
    [3x1 containers.Map]    [3x1 containers.Map]

>> a = [a, {dictA}]
a = 
    [3x1 containers.Map]    [3x1 containers.Map]    [3x1 containers.Map]

>> a{1}('first')
ans =
     1

We could have used a semicolon instead to concatenate them vertically a = [a; {dictA}]

Cell arrays, {}, and []

The way I think about this is that the {} are used to put things into cells (and also take them back out), and the [] are concatenation operations that also work on cell arrays.

a = {} assigns a to be an empty cell array.

a = [a, {dictA}] puts dictA into a cell and then concatenates this 1x1 cell array with cell array a.

a = [{a}, {dictA}] would have put a inside another cell array, leading to the weird nested cell array that you ran into.

a{1} returns the contents of the first cell in cell array a, which in this case is a Map object.

In my opinion, cell arrays and the use of the various brackets/parentheses is one of the most confusing things when learning MATLAB.

Careful! These are shallow copies

Note that this what MATLAB calls a "handle class", which means that a{1}, a{2}, and dictA are all pointers/references to the same object. Hence:

>> a{1}('fourth') = 4;
>> a
a = 
    [4x1 containers.Map]    [4x1 containers.Map]    [4x1 containers.Map]

Note that all 3 of these increased in size. Just wanted to warn you in case this is different from the behavior in Python (I don't know what the behavior in Python is).

Community
  • 1
  • 1
KQS
  • 1,547
  • 10
  • 21
0

A possible equivalent would be a cell containing structures:

octave:52> d1.val='one';d2.val='two';d3.val='three';
octave:53> c={d1,d2,d3};
octave:54> c
c = 
{
  [1,1] =
    scalar structure containing the fields:
      val = one
  [1,2] =
    scalar structure containing the fields:
      val = two
  [1,3] =
    scalar structure containing the fields:
      val = three
}
octave:55> c{2}.val
ans = two

cells have the content flexibility of a list. A structure is like a dictionary, though with more restrictions on the keys. Or may be you could liken them to Python objects. In fact the initial 'object' implementation in MATLAB was built on top of structures (in the late 1990s).

Another possibility is a structure array. From the Octave docs:

 x(1).a = "string1";
 x(2).a = "string2";
 x(1).b = 1;
 x(2).b = 2;

octave:65> x
x =
  1x2 struct array containing the fields:
    a
    b
octave:66> x(1)
ans =
  scalar structure containing the fields:
    a = string1
    b =  1

Sometimes it helps to write objects back and forth between MATLAB and numpy using scipy.io.loadmat/savemat. Those developers have worked out a set of equivalences.


Other SO questions comparing structures and containers:

The difference between a container map and a struct in matlab

Hash tables in MATLAB

MATLAB docs say containers are most efficient for holding small values - scalars(?) and strings. I haven't seen discussion of collecting containers in a cell.

If you are interested in a numpy/MATLAB data exchange collections could still be a problem - depending on how it saves them to .mat files.

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thank you. Can it be done as a ```cell array``` of ```map containers``` or would you advise against that? – Aaron Feb 16 '16 at 22:25
  • 1
    Digging around a bit I find that `map containers` have been around since 2008, and are based on a `Java` `hashmap`. They do look closer to Python dictionaries. A recent MATLAB SO question compares them with structures, http://stackoverflow.com/questions/34767016/the-difference-between-a-container-map-and-a-struct-in-matlab and http://stackoverflow.com/questions/3591942/hash-tables-in-matlab – hpaulj Feb 17 '16 at 00:07
  • Thank you. The links helped. – Aaron Feb 17 '16 at 15:56