Matlab “eval()”可以避免吗?(在运行时分配变量名)

Matlab “eval()”可以避免吗?(在运行时分配变量名),matlab,eval,Matlab,Eval,我已经编写了一个脚本,保存我在Matlab中手动导入测试期间记录的数据 每次测试运行都会在.csv文件中保存大约2600个变量,每个文件都有两行标题、两列数据和是分隔符 文件名来自监控程序使用的内部C-struct,因此属于这种类型:foo.bar.other.foo.bar.local_varname#VALUE.csv,我想用它在Matlab中重新创建结构,以便仅将其保存在test_name.mat文件中 很多时候,local\u varname的长度超过63个字符,因此我有一些替换规则,以

我已经编写了一个脚本,保存我在Matlab中手动导入测试期间记录的数据

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

文件名来自监控程序使用的内部C-struct,因此属于这种类型:
foo.bar.other.foo.bar.local_varname#VALUE.csv
,我想用它在Matlab中重新创建结构,以便仅将其保存在
test_name.mat
文件中

很多时候,
local\u 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()
:为什么会这样?在上述情况下,我可以避免吗

谢谢

编辑 正如@wakjah所建议的,我测试了一种
containers.Map()
方法。不幸的是,它不适合我们的需要,因为在这一点上,需要一个键列表,访问数据并不完全友好(请记住,我有大约2600个变量,这意味着至少有相同数量的键)

至于@Dennis Jaheruddin提出的问题,数据结构是可用的,不会产生任何冲突,即使使用这些长的变量名(假设两个连续
之间的每个名称*长度小于63个字符)

*我很抱歉没有使用Mathworks页面上更好的技术术语

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

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

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

ans =

       12345
这将把结构
s
中的
test
字段设置为
myFieldValue

洛伦也在博客中发表了关于这个主题的文章

编辑:由于要求字段名长度超过63个字符,另一种方法是使用
containers.Map
对象。这里有一个小例子:

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

ans =

       12345

您是否考虑过使用函数
genvarname
local\u varname
生成有效的唯一变量名?

查看您要做的事情后,我的第一个想法是您做得很奇怪

拥有超过63个字符的变量名称基本上是自找麻烦。相反,我建议采用以下简单的解决方案:

将结构与两个字段一起使用:

  • 文件名
  • 价值观
这样,数据的结构更加自然,所有文件只需要一个变量


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


我在这里能想到的唯一真正的缺点是,autocomplete对变量名有效,但对其内容无效,但这应该是一个很小的代价。

不幸的是,这种解决方案产生了另一种问题:对完整的
文件名{j}
施加63个字符的限制(在某些情况下,最多180个字符)使用
eval()
时,我只需要关心
local\u varname
。此外,如果
文件名{j}
包含
(对我来说总是如此)它将返回一个错误
eval如何避免这种情况?我刚刚试过——当字段名超过63个字符时,无论是否使用
eval
执行此操作,MATLAB都会发出警告。也许我误解了你。。。无论如何,如果你真的需要这么长的字段名,你有没有考虑过使用?例如:
filenames{1}=ABCDE.ABC0.ABCDE.ABC_AA_AA_AAA_AAA_00_BBB_CCCC_ABCDE_ABCDEFGHIJKLMNO_aa0.A_ABCDE__CCC_ddd_eeee aaaaaa bbbbbbbbbbbbbb cccccccccccccccc dddddddddddd 00
长,最后一部分为<153字符(现在71个字符长)到不到63个字符,我没有问题,你的代码1)我的
s有一个错误,2)它抱怨
文件名{1}
太长了。您需要这些变量作为本地工作区中的变量,有什么特别的原因吗?如果不是的话,我肯定会说地图是一个更有效和(也许更重要的)可读性更好的解决方案。我从未听说过地图,我会看看它们。一般来说,我以后必须进行数据后处理(例如,频率分析),是否可以使用映射进行后处理?是的,但我必须维护与原始程序相同的结构,因此我更喜欢手写规则,以便我知道什么对应于什么。此解决方案的示例代码如下: