2013-03-28 126 views
2

我写了一个脚本,可以帮助我在Matlab中手动导入测试期间记录的数据。可以避免`eval()`吗? (在运行时分配变量名称)

每个测试运行都会在.csv文件中保存约2600个变量,每个文件有2个标题行,两列数据和;是分隔符。

的文件名来从监视程序使用的内部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提出的要求是,数据结构是可用的并且不会产生任何类型的冲突,即使使用这些长的varnames(假设两个连续的.之间的每个名称*小于63个字符长)

*我很抱歉没有使用更好的技术术语

回答

3

this页面上Mathworks:

尽管eval函数非常强大且灵活,但并不总是解决编程问题的最佳解决方案。与使用其他函数或语言结构的代码相比,调用eval的代码通常效率更低,更难以阅读和调试。 ...

您可以很容易地使用圆括号表示法来完成您的任务。一个简单的例子:

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

这将在struct s设置test字段myFieldValue

也有this Loren在这个主题的博客文章。

编辑:由于您的要求是字段名称长度超过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'?我只是试了一下 - 当你的字段名长于63个字符时,MATLAB会发出警告,不管你是否使用'eval'。也许我误解了你......无论如何,如果你确实需要长时间的域名,你是否考虑过使用['containers.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字符,我没有问题,与你的代码1)我有一个错误的'.'s和2)它抱怨'文件名{1}'太长 – Federico

0

你有使用功能genvarnamelocal_varname产生有效的唯一变量名称考虑?

+0

是的,但我必须保持与原始程序相同的结构,所以我更喜欢手写规则,以便我知道与什么相对应。 – Federico

3

看过你想要做的事情后,我的第一个想法是,你做的很奇怪。

拥有超过63个字符的变量名基本上是在寻求麻烦。相反,我会推荐以下简单的解决方案:

使用结构有两个字段:

  • 价值

这样,你的数据更自然的结构,你只需要一个变量适用于所有文件。


请注意,值可以是结构或数组,并且不限于单个字符串或数字。

我在这里可以想到的唯一真正的缺点是自动完成工作的变量名称,但不是他们的内容,但这应该是一个小的代价。

+0

此解决方案的示例代码位于以下位置:http://stackoverflow.com/a/15439593/931379 – Pursuit

相关问题