2013-03-28 4 views
2

Я написал сценарий, который позволяет мне вручную импортировать в Matlab данные, записанные во время тестов.Можно ли избежать `eval()`? (Назначить имя переменной во время выполнения)

Каждый тестовый прогон сохраняет около 2600 переменных в файлах .csv, каждый из которых имеет две строки заголовка, два столбца данных и ; является разделителем.

Имена файлов происходят из внутреннего C-структуры, используемой программой мониторинга и, таким образом, такого рода: foo.bar.another.foo.bar.local_varname#VALUE.csv, и я хочу использовать это, чтобы заново создать структуры в Matlab для того, чтобы сохранить только то, что в test_name.mat файле ,

Много раз local_varname имеет длину более 63 символов, поэтому у меня есть некоторые правила подстановки, чтобы сократить имена без сокращения Matlab имен (и поэтому избегайте конфликтов имен).

Это код

clear all 
clc 

% Main names 
path_self   = pwd; 
backslash_indices = strfind(path_self,'\'); 
test_name   = path_self(backslash_indices(end)+1:end); % the directory name gives me the test_name 

% Preallocation 
filenames = cell(1,2600); 
addresses = cell(1,2600); 
i=0; 

% Full list 
MyFiles = dir(path_self); 

% Discard subdirectories and non interesting files 
for k=1:length(MyFiles) 
    if ~MyFiles(k).isdir, 
     if ~isempty(strfind(MyFiles(k).name,'#VALUE.csv')) 
      i=i+1; 
      % Too many files 
      if i > length(filenames) 
       filenames = [filenames cell(1,100)]; 
       addresses = [addresses cell(1,100)]; 
      end 
      % Naming Substitution Rules 

      %%% INSERT HERE BUNCH OF RULES 

      % Addresses and names 
      filenames{i} = strrep(filename,'#VALUE.csv',''); 
      addresses{i} = fullfile(path_self, MyFiles(k).name); 
     end 
    end 
end 
filenames = filenames(1:i); 
addresses = addresses(1:i); 

% Check that no conflicts are created 
if length(filenames) ~= length(unique(filenames)) 
    error('filenames not unique') 
end 

% Housekeeping #1 
clear MyFiles backslash_indices i k path_self 

% Import data 
for j=1:length(filenames) 
    % Read data 
    Data = importdata(addresses{j}, ';', 2); 
    % Assign data 
    eval([filenames{j}, '.time = Data.data(:,1)./1000000;']); % Converted in seconds 
    eval([filenames{j}, '.values = Data.data(:,2);']); 
    % Let's avoid data corruption 
    clear Data 
end 

% Housekeeping #2 
clear filenames addresses j 

% Save data struct 
save(test_name, '-regexp', '^((?!name).)*$') 

Теперь мой вопрос При исследовании информации и помочь написать код выше я часто люди хмуро на использовании eval(): почему это так? В приведенной выше ситуации я могу избежать этого?

Благодаря

EDIT Как было предложено @wakjah, я испытал containers.Map() подход. К сожалению, это не подходит для наших нужд, так как в этот момент необходим список ключей, и доступ к данным не совсем дружественный (помните, что у меня есть ~ 2600 переменных, что означает, по крайней мере, то же количество ключей)

Что касается то, что задал @Dennis Jaheruddin, структура данных применима и не создает каких-либо конфликтов даже с этими длинными именами (при условии, что каждое имя * между двумя последовательными . имеет длину менее 63 символов)

* мои извинения за неиспользование лучшего технического термина

ответ

3

От this страница Mathworks:

Хотя функция eval является очень мощной и гибкой, она не всегда является лучшим решением проблемы программирования. Код, который вызывает eval, часто менее эффективен и сложнее читать и отлаживать, чем код, который использует другие функции или языковые конструкции. ...

Вы можете легко использовать обозначение круглых скобок для выполнения своей задачи. Простой пример:

s = struct(); 
myFieldName = 'test'; 
s.(myFieldName) = myFieldValue; 

Это установит test поля в структурах s к myFieldValue.

Существует также сообщение this блога Лорена по этому вопросу.

Редактировать: Поскольку ваши требования состоят в том, чтобы имена полей были длиннее 63 символов, другим методом является использование объекта containers.Map.Вот небольшой пример:

>> m = containers.Map(); 
>> myFieldName = repmat('abcdefg', [1 10]); % 70 chars long 
>> m(myFieldName) = 12345; 
>> m(myFieldName) 

ans = 

     12345 
+0

К сожалению, это решение создает проблему другого типа: предел 63 символов наложен на полные 'filenames {j}' (в некоторых случаях это до 180 символов), а с 'eval()' мне нужно заботиться только о 'local_varname'. Кроме того, он возвращает ошибку, если 'filenames {j}' содержит '.' (всегда для меня случай) – Federico

+0

Как этого избежать с помощью' eval'? Я просто попробовал - MATLAB выдает предупреждение, выполняете ли вы это с помощью 'eval' или нет, когда ваше имя поля длиннее 63 символов. Возможно, я вас не понимаю ... Во всяком случае, если вам действительно нужны имена полей, которые вы долгое время рассматривали с помощью ['container.Map'] (http://www.mathworks.co.uk/help/matlab/map- containers.html)? – wakjah

+0

Пример: 'имена файлов {1} = ABCDE.ABC0.ABCDE.ABC_AA_AA_AAA_00.BBB_BBB_00_BBB_CCCC_ABCDE_ABCDEFGHIJKLMNO_AAAA0.A_ABCDE_CCC_DDDD_EEEEE_AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD00_DDDD0' (153 символа длина) С' Eval() ', если сжать последнюю часть (теперь 71 обугленной длиной) до менее чем 63 chars, у меня нет проблем, с вами код 1) У меня есть ошибка для '.'s и 2), он жалуется, что' filenames {1} 'слишком длинный – Federico

0

Рассматривали вы с помощью функции genvarname генерировать недействительные уникальные имена переменных из local_varname?

+0

да, но я должен поддерживать ту же структуру, что и в исходной программе, поэтому предпочитаю рукописные правила, чтобы я знал, что соответствует чему. – Federico

3

Посмотрев, что вы пытаетесь сделать, моя первая мысль заключается в том, что вы делаете странно.

Имея переменные имена более 63 символов, в основном задают проблемы. Вместо этого я бы рекомендовал следующее простое решение:

Используйте-структуру с двумя полями:

  • Имя файла
  • Значение

Таким образом, ваши данные структурированы более естественно и вам нужно будет только одна переменная для всех ваших файлов.


Обратите внимание, что значение может быть структурой или массивом и не ограничено одной строкой или номером.

Единственный реальный недостаток, который я могу придумать здесь, заключается в том, что автозаполнение работает с именами переменных, но не по их содержимому, но это должна быть небольшая цена для оплаты.

+0

Пример кода для этого решения находится здесь: http://stackoverflow.com/a/15439593/931379 – Pursuit

Смежные вопросы