4

in Matlab I have several records of a database stored in the matrix DataMatrix. Each row of the matrix is a record and each column is the value of a property of the record. To make the program easy to understand for each column of DataMatrix I defined a variable name explaining what property is associated to the column, that is:

ColApple = 1;
ColOrange = 2;
ColLemon = 3;
...

I have about 50 columns to name.

My problem is that the values in DataMatrix are used in different functions and I would like to always use the columns name to work on the data in DataMatrix. So I have to share between different functions the values of ColApple, ColOrange, ColLemon, ...

Up to now I thought to two possible approaches:

  1. Making the columns name global

  2. Define a function returning the values for the columns name, that is:

    [ColApple, ColOrange, ColLemon, ... ] = getColNames

I would avoid the global solution because I think it is dangerous and also because I would like the columns name constant if possible. The second approach is better but since I have 50 columns I do not know if it is a good idea to have a function returning 50 different values (also it is difficult to maintain in my opinion).

Anyone has a more robust or maintainable approach to solve this problem? I am sure I am not the first one to deal with this but I was not able to find a solution.

Community
  • 1
  • 1
MeSS83
  • 349
  • 2
  • 7
  • 20

2 Answers2

7

This is perfect for container maps. A container map allows for creating a dictionary. For example

fruits = containers.Map({'Apple', 'Orange', 'Lemon'}, [1, 2, 3])

will create the dictionary

'Apple'   ->   1
'Orange'  ->   2
'Lemon'   ->   3

you can find the desired column number with

>> fruits('Orange')

ans =

     2
hbaderts
  • 14,136
  • 4
  • 41
  • 48
2

Don't use global variables, as they are prone to errors. Creating 50 variable names is not very error-proof either (see: dynamic variable naming).

I'd go with a simple cell array in this case. You can either read the names from the first row in your data matrix if they are written there, or hand write them if you're doing that now anyway.

ColumnNames = {'Col1', 'Col2', 'Col3', (...) , 'Col 50'}

This will give you a 1 x 50 cell array containing your column names. The names can be found simply by entering the correct column number, i.e. column 22 would be ColumnNames{1,22}. You can now pass the variable ColumnNames to other functions as just a single variable. In order to get the corresponding column name if you do not use dynamic variable naming, but e.g. your colApple, you can use strcmp

ColIdx = find(strcmp(ColumnNames,'colApple'));

This way the strcmp checks which cell contains the string 'colApple', and the find returns the index number of the requested cell.

I pass a lot of variables in my own code, which I do in a structure array, since that's able to store all kinds of different data and have a reasonable name for each structure entry:

result.data = [m x 9 double]
result.grid.z = ~[5000 x 5500 double]
result.filename = 'filename.asc'
...
Community
  • 1
  • 1
Adriaan
  • 17,741
  • 7
  • 42
  • 75
  • thanks but I am not sure I fully understand the answer. Using your example `ColumnNames{1,22}` returns `Col 22` so, given the column number I get the column name. Given the two functions `function1` and `function2` and I pass to them the variable `ColumnNames` I am sure that , given the same column number, I get the same column name. But what I am looking for is the contrary: given the same column name I would like to have the same column number. This way the command `DataMatrix(:, Col22) = something` would work on the same column both in `function1` and `function2` – MeSS83 Jan 23 '16 at 10:12
  • Maybe you think that after passing `ColumnNames` I should create the variables using something like `for ii = 1: length(ColumnNames) str = [ColumnNames{1,ii} ' = ' int2str(ii)]; eval(str); end` – MeSS83 Jan 23 '16 at 10:13
  • @MeSS83 I never think that using `eval` is a good idea, ever. See the linked post about using Dynamic Variable Names. `eval` breaks everything MATLAB related and is not to be used in my opinion. If you do not move columns around in your data, then if you pass your data from one function to another, column 22 will still be column 22, so I don't see the problem there. – Adriaan Jan 23 '16 at 10:22
  • you are perfectly right column 22 in my case is always column 22 but in my code I did not write `DataMatrix(:, 22) = something` but instead I have `DataMatrix(:, ColLemon) = something`. I did this because I thought It was more readable and because maybe in the future the value of `ColLemon` will change. So I would ensure that in every function of my program `ColLemon` has the same value. I simply do not understand how to use your solution, passing `ColumnNames`, to achieve this – MeSS83 Jan 23 '16 at 10:32
  • @MeSS83 and rightly so. I didn't know about container maps, so I hacked my way there. I do urge you to read through my linked answer on Dynamic Variable Naming though, to prevent you from using `eval`, with all its associated pitfalls and breakdowns. – Adriaan Jan 23 '16 at 11:19